Merge branch 'master' of rvb.name:openhab-process
authorRoman Bazalevskiy <rvb@rvb.name>
Sun, 16 Sep 2018 16:08:55 +0000 (19:08 +0300)
committerRoman Bazalevskiy <rvb@rvb.name>
Sun, 16 Sep 2018 16:08:55 +0000 (19:08 +0300)
mqtt-agi/clear-sms-spool [new file with mode: 0644]
mqtt-agi/mqtt
mqtt-agi/mqtt-sms [new file with mode: 0755]
mqtt-bt/scan-beacons
mqtt-mpd/mqmpd
mqtt-mpd/mqmpdj

diff --git a/mqtt-agi/clear-sms-spool b/mqtt-agi/clear-sms-spool
new file mode 100644 (file)
index 0000000..b8814b4
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+reload(sys)
+sys.setdefaultencoding('utf-8')
+
+from ConfigParser import ConfigParser
+import paho.mqtt.client as paho
+from pymessaging.sms import SmsDeliver
+
+import sqlite3
+from sqlite3 import Error
+
+from tempfile import mkstemp
+from shutil import move
+
+conffile = sys.argv[1:2]
+
+config = ConfigParser()
+config.add_section('sms')
+# set defaults for anonymous auth
+config.set('sms', 'tmpfile', '/tmp/sms.db')
+config.read(conffile)
+
+sms_db = config.get('sms','tmpfile')
+
+try:
+  conn = sqlite3.connect(sms_db)
+
+  cur = conn.cursor()
+  cur.execute("select ref from sms_parts group by ref having max(datetime) is null or (julianday('now')-julianday(max(datetime)))>0.005;")
+  refs=cur.fetchall()
+  for ref in refs:
+    cur.execute("select text from sms_parts where ref=%s order by seq" % (ref))
+    full_text=''.join(rec[0] for rec in cur.fetchall()).replace("\"","")
+    f,path=mkstemp(suffix=".call")
+    f=open(path,"w")
+    f.write("Application: Dial\n")
+    f.write("Channel: Local/smsraw@DID_mobile\n")
+    f.write("Context: smsraw\n")
+    f.write("Setvar: SMS_FULL_TEXT=%s" % full_text)
+    f.close()
+    move(path,'/var/spool/asterisk/outgoing')
+    cur.execute("delete from sms_parts where ref=%s" % (ref))
+    conn.commit()
+
+except:
+  None
\ No newline at end of file
index 6f69c7edcf1ee07607a4bbe9d81290cebf10aa85..cbb3e25fb2c9f884275452ddb9a02fe5140416a1 100755 (executable)
@@ -13,8 +13,12 @@ import paho.mqtt.client as paho
 
 import json
 
+from os import getpid,uname
 from pprint import pprint
 
+client_name='agi-'+uname()[1]+'-'+str(getpid())
+print client_name
+
 conffile, topic = sys.argv[1:3]
 
 config = ConfigParser()
@@ -55,7 +59,7 @@ def on_publish(mosq, *args):
     # done
     agi_exit(0)
 
-client = paho.Client('agi')
+client = paho.Client(client_name)
 client.username_pw_set(mqtt_username, mqtt_password)
 client.connect(mqtt_server, port=mqtt_port)
 client.on_connect = on_connect
diff --git a/mqtt-agi/mqtt-sms b/mqtt-agi/mqtt-sms
new file mode 100755 (executable)
index 0000000..ba1cdd5
--- /dev/null
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#
+# Usage:
+# AGI(/etc/asterisk/agi/mqtt,/etc/asterisk/agi/mqtt.cfg,calls/missed)
+# or, to override the extension:
+# AGI(/etc/asterisk/agi/mqtt,/etc/asterisk/agi/mqtt.cfg,calls/missed,+43123456789)
+#
+
+import sys
+reload(sys)
+sys.setdefaultencoding('utf-8')
+
+from ConfigParser import ConfigParser
+import paho.mqtt.client as paho
+from pymessaging.sms import SmsDeliver
+
+import json
+
+from os import getpid,uname
+from pprint import pprint
+
+import sqlite3
+from sqlite3 import Error
+
+from os import remove,system
+
+client_name='agi-'+uname()[1]+'-'+str(getpid())
+
+conffile, topic, base64 = sys.argv[1:4]
+
+config = ConfigParser()
+config.add_section('mqtt')
+config.add_section('sms')
+# set defaults for anonymous auth
+config.set('mqtt', 'username', '')
+config.set('mqtt', 'password', '')
+config.set('mqtt', 'port', '1883')
+config.set('sms', 'tmpfile', '/tmp/sms.db')
+config.read(conffile)
+
+mqtt_server = config.get('mqtt', 'server')
+mqtt_port = config.getint('mqtt', 'port')
+mqtt_username = config.get('mqtt', 'username')
+mqtt_password = config.get('mqtt', 'password')
+sms_db = config.get('sms','tmpfile')
+
+try:
+  conn = sqlite3.connect(sms_db)
+except:
+  remove(sms_db)
+  conn = sqlite3.connect(sms_db)
+
+agi = []
+while 1:
+    line = sys.stdin.readline()
+    if not line or line == "\n":
+        break
+    agi.append(line)
+
+agi = dict([line.rstrip('\n').replace('agi_', '', 1).split(': ', 1) for line in agi])
+
+agi['base64'] = base64
+
+full_text=""
+try:
+  sms=SmsDeliver(base64.decode('base64').split('\r\n')[1])
+  if 'cnt' in sms.data:
+    sms_type='sms-multipart'
+    part_count=sms.data['cnt']
+    part_number=sms.data['seq']
+    ref=sms.data['ref']
+    agi['part-count']=part_count
+    agi['part-number']=part_number
+    agi['ref']=ref
+  else:
+    sms_type='sms'
+  agi['sms-type']=sms_type
+  sms_text=sms.data['text'].encode('utf-8')
+  agi['sms_text']=sms_text
+  if sms_type=='sms':
+    full_text=sms_text
+  else:
+    cur = conn.cursor()
+    cur.execute("create table if not exists sms_parts (ref integer,cnt integer,seq integer,datetime timestamp default current_timestamp,text varchar(255))")  
+    cur.execute("insert into sms_parts(ref,cnt,seq,text) values(%s,%s,%s,\'%s\')" % (ref,part_count,part_number,sms_text))
+    cur.execute("select count(*),cnt from sms_parts where ref=%s" % (ref))
+    received,cnt=cur.fetchone()
+    if received==cnt:
+      cur.execute("select text from sms_parts where ref=%s order by seq" % (ref))
+      full_text=''.join(rec[0] for rec in cur.fetchall())
+#      full_text=full_text.replace("\"","")
+      agi["full_text"]=full_text
+      cur.execute("delete from sms_parts where ref=%s" % (ref))
+    conn.commit()  
+except:
+  raise
+
+if full_text:
+  print full_text
+  f1=open("/tmp/sms.log","w+")
+  f1.write(full_text.strip().encode('utf-8'))
+  f1.close()
+  
+def agi_exit(rc, *args):
+    if rc != 0:
+        print "VERBOSE rc=%s %s" % (rc, args)
+    sys.exit(rc)
+
+def on_connect(mosq, rc, *args):
+    if rc != 0:
+        agi_exit(1, "Connection failed: %d" % rc)
+
+def on_publish(mosq, *args):
+    # done
+    agi_exit(0)
+
+client = paho.Client(client_name)
+client.username_pw_set(mqtt_username, mqtt_password)
+client.connect(mqtt_server, port=mqtt_port)
+client.on_connect = on_connect
+client.on_publish = on_publish
+
+client.publish(topic, payload=json.dumps(agi))
+client.loop()
+agi_exit(1, "Message publish timed out")
index b73d6747abdad876a4937f85eecf9e5c7790ea5f..17e553308c15a067544f4b337a62603469215b39 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/lua
 
+json = require("json")
+
 function getConfig(configname)
 
   local uci=require("uci")
@@ -22,7 +24,11 @@ function getConfig(configname)
   mqtt_passwd = cur.get(config,"mqtt","password")
 
   if mqtt_host and not mqtt_id then
-    mqtt_id="beaconmon"
+    socket = require("socket")
+    posix = require("posix")
+    hostname = socket.dns.gethostname()
+    pid = posix.getpid()
+    mqtt_id="beaconmon-"..hostname.."-"..pid
   end
 
   if mqtt_host and not mqtt_port then
@@ -57,7 +63,7 @@ function mqtt_encode(str)
 end
 
 function printLog(str)
-  if logging=="on" then
+  if logging=="yes" then
     capture("logger -t beaconmon "..str)
   else 
     print(str)  
@@ -74,29 +80,19 @@ end
 
 function open_dump()
 
-  run_command("/bin/kill `/usr/bin/pgrep hcidump`")
+  run_command("/bin/kill `/usr/bin/pgrep btmon`")
   run_command("/bin/kill `/usr/bin/pgrep hcitool`")
-  f = assert(io.popen ("/usr/bin/hcidump --raw"))
+  f = assert(io.popen ("/usr/bin/stdbuf -o0 /usr/bin/btmon"))
   run_command("/usr/bin/hciconfig hci0 down")
   run_command("/usr/bin/hciconfig hci0 up")
-  f_null = assert(io.popen ("/usr/bin/hcitool lescan --duplicates"))
+  f_null = assert(io.popen ("/usr/bin/hcitool lescan --duplicates --passive"))
 
   return f
 
 end
 
 function dump(o)
-   if type(o) == 'table' then
-      local s = '{ '
-      for k,v in pairs(o) do
-         if type(k) ~= 'number' then k = '"'..k..'"' end
-         s = s .. '['..k..'] = ' .. dump(v) .. ','
---         s = s .. dump(v) .. ','
-      end
-      return s .. '} '
-   else
-      return tostring(o)
-   end
+  return json.encode(o)
 end
 
 function trim(s)
@@ -104,131 +100,132 @@ function trim(s)
 end
 
 function mqtt_pub(path,value)
-  printLog("Pub "..path.." "..value)
-  return mqtt_client:publish(path,value)
+  res=mqtt_client:publish(path,value)
+  printLog("Pub "..path.." "..value.." returned "..res);
+  return res
 end
 
 function process_packet(packet)
 
-  local bytes={}
-  local idx=1
-  local len
   local mac
-  local flags
-  local power
-  local tx
-  local type
-  local paysublen
   local uuid
-  local major
-  local minor
   local details
+  local type
+  local name
+
+  mac = packet['Address']
+  uuid = packet['uuid']
+  type = packet['Type']
+  name = packet['Name (complete)']
+
+  if type=='iBeacon' then
+    details=uuid
+  elseif name then
+    if not(type) then
+      type="name"
+    end  
+    details=name
+  else
+    if not type then 
+      type='unknown'
+    end  
+    details=mac
+  end
 
-  if packet:len()>1 then
-
-    while packet:len()>2 do
-      bytes[idx]=trim(packet:sub(1,3))
-      idx=idx+1
-      packet=packet:sub(4)
-    end
-    len = idx-1
-
-    if bytes[1]=='04' and bytes[2]=='3E' then
-      -- BLE Beacon?
-      type=""
-      mac=bytes[13]..':'..bytes[12]..':'..bytes[11]..':'..bytes[10]..':'..bytes[9]..':'..bytes[8]
-      flags=bytes[14]
-      power=tonumber("0x"..bytes[len-1])-256
-      tx=tonumber("0x"..bytes[len])-256
-      local j = 15
-      while j<len-2 do
-        paysublen=tonumber('0x'..bytes[j])
-       if bytes[j+1]=="FF" and bytes[j+2]=="4C" and bytes[j+3]=="00" and bytes[j+4]=="02" and bytes[j+5]=="15" then
-         -- Standard UUID iBeacon
-          type="ibeacon"
-         local uuid1=bytes[j+6]..bytes[j+7]..bytes[j+8]..bytes[j+9]
-         local uuid2=bytes[j+10]..bytes[j+11]
-         local uuid3=bytes[j+12]..bytes[j+13]
-         local uuid4=bytes[j+14]..bytes[j+15]
-         local uuid5=bytes[j+16]..bytes[j+17]..bytes[j+18]..bytes[j+19]..bytes[j+20]..bytes[j+21]
-         uuid=string.lower(uuid1..'-'..uuid2..'-'..uuid3..'-'..uuid4..'-'..uuid5)
-          major=bytes[j+23]..bytes[j+22]
-          minor=bytes[j+25]..bytes[j+24]
-       end
-        j=j+1+paysublen
-      end
-      if type=="ibeacon" then
-        printLog(string.format("{type:'ibeacon',mac:'%s',uuid:'%s',major:'%s',minor:'%s',power:%d,tx:%d}",mac,uuid,major,minor,power,tx))
-        details=uuid..'/'..major..'/'..minor
-      else
-        type='unknown'
-        details=dump(bytes)
---        printLog(details)
-      end
-      if not (type=="unknown") then
-        mqtt_path=string.gsub(mqtt_topic,"{(.-)}", 
-          function (name) 
-            if name=="type" then
-              return mqtt_encode(type)
-            elseif name=="details" then
-              return mqtt_encode(details)
-            else
-              return '{'..name..'}'
-            end      
-          end)
+  if not (type=="unknown") then
+    mqtt_path=string.gsub(mqtt_topic,"{(.-)}",
+      function (name) 
+        if name=="type" then
+          return mqtt_encode(type)
+        elseif name=="details" then
+          return mqtt_encode(details)
+        else
+          return '{'..name..'}'
+        end      
+      end)
         
-        if not pcall(mqtt_pub,mqtt_path,tx) then
-          printLog('Reconnecting MQTT...')
-          mqtt_client:connect(mqtt_id)
-        end
-
-      end        
+    if not pcall(mqtt_pub,mqtt_path,dump(packet)) then
+      printLog('Reconnecting MQTT...')
+      mqtt_client:connect(mqtt_id)
     end
+
   end
 
 end
 
-function read_loop()
-
-  packet = ""
-
-  for line in inp:lines() do
-
-    lchr=line:sub(1,1)
-    line=trim(line)
-
-    if lchr=="<" or lchr==">" then
-      line = trim(line:sub(2))
-    end
+function starts(String,Start)
+   return string.sub(String,1,string.len(Start))==Start
+end
 
-    if not (lchr == " ") then
-      process_packet(packet)
-      packet = ""
-    end
+function split(inputstr, sep)
+        if sep == nil then
+                sep = "%s"
+        end
+        local t={} ; i=1
+        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
+                t[i] = str
+                i = i + 1
+        end
+        return t
+end
 
-    llen=line:len()
+function read_loop()
 
-    if llen<59 then
-      packet = packet .. " " .. line
-      process_packet(packet)
-      packet=""
-    else
-      packet = packet .. " " .. line
-    end    
+  packet={}
+  inbound=false
+
+  while true do
+
+    str=inp:read("*l")
+
+    if str then 
+
+      str=trim(str)
+
+      if inbound then
+        t = split(str,':')
+        if #t>=2 then
+          name=t[1]
+          value=trim(table.concat(t,':',2))
+          if name=="Address" then
+            value=split(value)[1]
+          end
+          packet[name]=value
+        elseif #t==1 and name then
+          if not(packet[name..'.list']) then
+            packet[name..'.list']={}
+          end  
+          table.insert(packet[name..'.list'],(trim(t[1])))
+        end  
+      end  
+
+      if starts(str,'> HCI Event: LE Meta Event (0x3e)') then
+        inbound=true
+        name=nil
+      elseif starts(str,'RSSI:') then
+        inbound=false
+        process_packet(packet)
+        packet={}
+      end
+      
+    end  
     
   end
 
 end
 
+io.stdout:setvbuf('no')
+io.stdin:setvbuf('no') 
+
 getConfig(arg[1])
 
 if mqtt_host then
-  MQTT = require "paho.mqtt"
-  mqtt_client = MQTT.client.create(mqtt_host, mqtt_port)
+  MQTT = require "mosquitto"
+  mqtt_client = MQTT.new(mqtt_id)
   if mqtt_user then
-    mqtt_client:auth(mqtt_user, mqtt_passwd)
+    mqtt_client:login_set(mqtt_user, mqtt_passwd)
   end
-  mqtt_client:connect(mqtt_id)
+  mqtt_client:connect(mqtt_host,mqtt_port)
 end
 
 inp = open_dump()
index 5d378ea140a912862b797c4d3620e3a0ca2db6d8..595c08d9ca9b5f7dfd2b78a4377394a227651f81 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+id=`hostname`-$$
+
 if [ "$1" = "stop" ] 
 then
 
@@ -28,7 +30,7 @@ done
 
 # сами остаемся слушать команды
 
-mosquitto_sub -v -h $mqhost -p $mqport -t "$mqcmd/#" -u $mquser -P $mqpassword | while read line
+mosquitto_sub -i mqtt-mpd-$id -v -h $mqhost -p $mqport -t "$mqcmd/#" -u $mquser -P $mqpassword | while read line
 do
 
   template="s!$mqcmd/!!"
@@ -113,7 +115,6 @@ do
        esac
        ;;
     currentnum)
-       $mpccmd pause
        $mpccmd play $arg
        ;;
     repeat|random|single|consume)
index 70603f2f9a98d7e67bd1f7c32c82700cc2595e57..b8c935ad9544d2ced63dda2b37e74aadf6862f49 100755 (executable)
@@ -2,6 +2,8 @@
 
 . /opt/mqtt-mpd/mqmpd.cfg
 
+id=`hostname`-$$
+
 host=$1
 passwd=$2
 
@@ -18,9 +20,6 @@ fi
 
 while : 
 do         
-  $command idle
-  if [ $? = 0 ]
-  then
 #    current=`mpc -h $host -P $passwd current | sed 's/"/\"/g'`
 #    volume=`mpc -h $host -P $passwd volume | cut -d: -f2 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'`
     
@@ -41,37 +40,57 @@ do
       single=${str3[7]}
       consume=${str3[9]}
     else
-      current='-'
-      status='stopped'
-      current_track_num='0'
-      tracks_in_list='0'
-      current_pos='-'
-      track_length='-'
-      str3=( ${array[0]})
-      volume=`echo ${str3[1]} | sed 's/%//'`
-      if [ "$volume" = "n/a" ]
+      if [ ${#array[@]} = 1 ]
       then
+        current='-'
+        status='stopped'
+        current_track_num='0'
+        tracks_in_list='0'
+        current_pos='-'
+        track_length='-'
+        str3=( ${array[0]})
+        volume=`echo ${str3[1]} | sed 's/%//'`
+        if [ "$volume" = "n/a" ]
+        then
+          volume="0"
+        fi
+        repeat=${str3[3]}
+        random=${str3[5]}
+        single=${str3[7]}
+        consume=${str3[9]}
+      else
+        # not responding or error
+        current='-'
+        status='failed'
+        current_track_num='0'
+        tracks_in_list='0'
+        current_pos='-'
+        track_length='-'
         volume="0"
-      fi
-      repeat=${str3[3]}
-      random=${str3[5]}
-      single=${str3[7]}
-      consume=${str3[9]}
+        repeat="off"
+        random="off"
+        single="off"
+        consume="off"
+      fi  
     fi  
+   
+    sleep 0.2
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/nowplaying -m "$current" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/volume -m "$volume" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/status -m "$status" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/currentnum -m "$current_track_num" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/tracks -m "$tracks_in_list" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/currentpos -m "$current_pos" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/tracklen -m "$track_length" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/repeat -m "$repeat" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/random -m "$random" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/single -m "$single" -u $mquser -P $mqpassword
+    mosquitto_pub -i mqtt-mpd-$id -h $mqhost -p $mqport -t $mqtopic/$host/consume -m "$consume" -u $mquser -P $mqpassword
 
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/nowplaying -m "$current" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/volume -m "$volume" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/status -m "$status" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/currentnum -m "$current_track_num" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/tracks -m "$tracks_in_list" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/currentpos -m "$current_pos" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/tracklen -m "$track_length" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/repeat -m "$repeat" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/random -m "$random" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/single -m "$single" -u $mquser -P $mqpassword
-    mosquitto_pub -h $mqhost -p $mqport -t $mqtopic/$host/consume -m "$consume" -u $mquser -P $mqpassword
-
-  else
-    sleep 30
-  fi  
+    $command idle
+    if [ $? != 0 ]
+    then
+      sleep 60
+    fi
+  
 done