-
Notifications
You must be signed in to change notification settings - Fork 15
/
ninjaCapeSerialMQTTBridge.py
executable file
·140 lines (114 loc) · 3.57 KB
/
ninjaCapeSerialMQTTBridge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/python
#
# used to interface the NinjaCape to openHAB via MQTT
# - reads data from serial port and publishes on MQTT client
# - writes data to serial port from MQTT subscriptions
#
# - uses the Python MQTT client from the Mosquitto project http://mosquitto.org (now in Paho)
#
# https://github.com/perrin7/ninjacape-mqtt-bridge
# perrin7
import serial
import paho.mqtt.client as mqtt
import os
import json
import threading
import time
### Settings
serialdev = '/dev/ttyO1' # for BBB
# serialdev = '/dev/ttyAMA0' # for RPi
broker = "127.0.0.1" # mqtt broker
port = 1883 # mqtt broker port
debug = False ## set this to True for lots of prints
# buffer of data to output to the serial port
outputData = []
#### MQTT callbacks
def on_connect(client, userdata, flags, rc):
if rc == 0:
#rc 0 successful connect
print "Connected"
else:
raise Exception
#subscribe to the output MQTT messages
output_mid = client.subscribe("ninjaCape/output/#")
def on_publish(client, userdata, mid):
if(debug):
print "Published. mid:", mid
def on_subscribe(client, userdata, mid, granted_qos):
if(debug):
print "Subscribed. mid:", mid
def on_message_output(client, userdata, msg):
if(debug):
print "Output Data: ", msg.topic, "data:", msg.payload
#add to outputData list
outputData.append(msg)
def on_message(client, userdata, message):
if(debug):
print "Unhandled Message Received: ", message.topic, message.paylod
#called on exit
#close serial, disconnect MQTT
def cleanup():
print "Ending and cleaning up"
ser.close()
mqttc.disconnect()
def mqtt_to_JSON_output(mqtt_message):
topics = mqtt_message.topic.split('/');
## JSON message in ninjaCape form
json_data = '{"DEVICE": [{"G":"0","V":0,"D":' + topics[2] + ',"DA":"' + mqtt_message.payload + '"}]})'
return json_data
#thread for reading serial data and publishing to MQTT client
def serial_read_and_publish(ser, mqttc):
ser.flushInput()
while True:
line = ser.readline() # this is blocking
if(debug):
print "line to decode:",line
# split the JSON packet up here and publish on MQTT
json_data = json.loads(line)
if(debug):
print "json decoded:",json_data
try:
device = str( json_data['DEVICE'][0]['D'] )
data = str( json_data['DEVICE'][0]['DA'] )
mqttc.publish("ninjaCape/input/"+device, data)
except(KeyError):
# TODO should probably do something here if the data is malformed
pass
############ MAIN PROGRAM START
try:
print "Connecting... ", serialdev
#connect to serial port
ser = serial.Serial(serialdev, 9600, timeout=None) #timeout 0 for non-blocking. Set to None for blocking.
except:
print "Failed to connect serial"
#unable to continue with no serial input
raise SystemExit
try:
#create an mqtt client
mqttc = mqtt.Client("ninjaCape")
#attach MQTT callbacks
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
mqttc.on_message = on_message
mqttc.message_callback_add("ninjaCape/output/#", on_message_output)
#connect to broker
mqttc.connect(broker, port, 60)
# start the mqttc client thread
mqttc.loop_start()
serial_thread = threading.Thread(target=serial_read_and_publish, args=(ser, mqttc))
serial_thread.daemon = True
serial_thread.start()
while True: # main thread
#writing to serial port if there is data available
if( len(outputData) > 0 ):
#print "***data to OUTPUT:",mqtt_to_JSON_output(outputData[0])
ser.write(mqtt_to_JSON_output(outputData.pop()))
time.sleep(0.5)
# handle app closure
except (KeyboardInterrupt):
print "Interrupt received"
cleanup()
except (RuntimeError):
print "uh-oh! time to die"
cleanup()