1417 lines
55 KiB
Python
1417 lines
55 KiB
Python
import sys
|
|
import string
|
|
import socket
|
|
import fcntl
|
|
import struct
|
|
import client as paho
|
|
import os
|
|
import re
|
|
import time
|
|
import ssl
|
|
try:
|
|
import json
|
|
except:
|
|
import simplejson as json
|
|
import thread
|
|
import threading
|
|
import random
|
|
import base64
|
|
|
|
from meshifyData import meshifyData
|
|
# from devices import mainMistaway, m1, apg #, gds #cam,
|
|
#from devices import gdsMT as gds
|
|
import Queue
|
|
import pickle
|
|
import urllib2
|
|
import urllib
|
|
try:
|
|
from sqlQueue import myqueue as SQLQ
|
|
except:
|
|
pass
|
|
try:
|
|
import SkyWaveDataAPI
|
|
SAT = True
|
|
except:
|
|
SAT = False
|
|
|
|
try:
|
|
import schedule
|
|
sced = True
|
|
except:
|
|
sced = False
|
|
|
|
unitName = "mainMeshify"
|
|
|
|
broker = "hp.henrypump.cloud"
|
|
|
|
root = os.getcwd() + "/"
|
|
# non secure
|
|
port = 1883
|
|
|
|
LORA = True
|
|
try:
|
|
import lora_main
|
|
except:
|
|
LORA = False
|
|
|
|
|
|
# secure port
|
|
#port = 1883
|
|
|
|
# driver for a virtual device called "main", it can never send data up to the website, but it hold methods that
|
|
# can be called easier than others because it has no unquie name assosicated with it
|
|
class main():
|
|
|
|
def __init__(self, name, number, mac, q, mcu, company, offset, mqtt, nodes, topics):
|
|
self.topics = topics
|
|
self.nodes = nodes
|
|
self.offset = offset
|
|
self.company = company
|
|
self.name = name
|
|
self.number = number
|
|
self.q = q
|
|
self.mqtt = mqtt
|
|
# + '_[' + mac + ':' + number[0:2] + ':' + number[2:] + ']!'
|
|
self.deviceName = name
|
|
print('device name is:')
|
|
print(self.deviceName)
|
|
mac2 = mac.replace(":", "")
|
|
self.mac = mac2.upper()
|
|
self.mcu = mcu
|
|
self.count = 0
|
|
self.dst = ""
|
|
# queue for sets to the mesh network will handeled through a queue in this main driver
|
|
self.meshQ = Queue.Queue()
|
|
version = "17" # 6 - mistification # 5 - updated for SAT data and generic sets. 4 - devices changed to drivers for dia
|
|
|
|
# self.sendtodb("version", version, 0)
|
|
thread.start_new_thread(self.registerThread, ())
|
|
|
|
#pickle.dump( version, open( "coreVersion.p", "wb" ) )
|
|
|
|
def sendtodb(self, channel, value, timestamp):
|
|
|
|
csplit = re.split(r"(.*?)_\[(.*?)\]", self.deviceName)
|
|
nodeTypeName = csplit[1]
|
|
uniqueID = csplit[2]
|
|
company = "194"
|
|
topic = "v1/devices/me/telemetry"
|
|
print(topic)
|
|
|
|
msg = """[{"%s":"%s"}]""" % (channel, str(value))
|
|
print(msg)
|
|
self.q.put([topic, msg, 0])
|
|
|
|
def getTime(self):
|
|
return str(int(time.time() + int(self.offset)))
|
|
|
|
def main_mcuupdate(self, name, value):
|
|
success = self.mcu.firmUpdate(value)
|
|
|
|
if success == True:
|
|
val = "update to " + value + " was a success"
|
|
elif success == False:
|
|
print("you need to reboot and pray you didn't brick the MCU")
|
|
val = "update to " + value + " failed"
|
|
else:
|
|
val = "update to " + value + " failed because " + str(success)
|
|
print("you need to reboot and pray you didn't brick the MCU")
|
|
|
|
# reseting the MCU also resets the Cellular modem, so we need to redo our mqtt connection once the modem comes back to life
|
|
time.sleep(180)
|
|
try:
|
|
self.mqtt.reconnect()
|
|
except Exception as e:
|
|
print(str(e))
|
|
os.system("/root/reboot")
|
|
self.sendtodb(name, val, 0)
|
|
|
|
def normalThread(self):
|
|
time.sleep(10)
|
|
os.system("/root/normalStart.sh")
|
|
|
|
def debugThread(self):
|
|
time.sleep(10)
|
|
os.system("/root/debugStart.sh")
|
|
|
|
def rebootThread(self):
|
|
time.sleep(10)
|
|
os.system("/root/reboot")
|
|
|
|
def main_normal(self, name, value):
|
|
|
|
if int(value) == 1:
|
|
|
|
thread.start_new_thread(self.normalThread, ())
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def main_debug(self, name, value):
|
|
|
|
if int(value) == 1:
|
|
|
|
thread.start_new_thread(self.debugThread, ())
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def main_reboot(self, name, value):
|
|
if bool(value) == True:
|
|
# reset the modem
|
|
# self.mcu.resetModem()
|
|
# time.sleep(2)
|
|
|
|
# resest the MCU
|
|
# try:
|
|
# os.system("/root/mcu2reset")
|
|
# except:
|
|
# pass
|
|
thread.start_new_thread(self.rebootThread, ())
|
|
return True
|
|
|
|
# os.system("/root/reboot")
|
|
|
|
def main_SAT(self, name, value):
|
|
print("SAT is SET in MAIN")
|
|
st = "date -s @" + str(int(float(value)))
|
|
os.system(st)
|
|
|
|
return True
|
|
|
|
def registerThread(self):
|
|
while True:
|
|
time.sleep(3600 * 24)
|
|
|
|
try:
|
|
os.system("/usr/bin/ntpdate pool.ntp.org")
|
|
os.system("/usr/sbin/ntpdate pool.ntp.org")
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
for name, driver in self.nodes.iteritems():
|
|
|
|
try:
|
|
driver.offset = self.offset
|
|
driver.company = self.company
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
except:
|
|
pass
|
|
|
|
def main_register(self, name, value):
|
|
# try and sync the time
|
|
|
|
try:
|
|
#setData = """<data><channel_set name="%s" value="%s"/></data>$$$%s""" % ("main.register", "On", 1)
|
|
setData = {}
|
|
setData['name'] = 'main.register'
|
|
setData['value'] = 'On'
|
|
setData['id'] = 1
|
|
print(setData)
|
|
self.meshQ.put(setData)
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
meshData = meshifyData.meshifyData(self.mac)
|
|
self.offset, self.dst, self.company = meshData.getdata()
|
|
csplit = re.split(r"(.*?)_\[(.*?)\]", self.deviceName)
|
|
nodeTypeName = csplit[1]
|
|
uniqueID = csplit[2]
|
|
company = "194"
|
|
|
|
print(("meshify/sets/" + str(self.company) + "/" + self.mac + "/#"))
|
|
self.mqtt.subscribe(("v1/devices/me/requests/+"), 0)
|
|
self.mqtt.append("v1/devices/me/telemetry")
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
for name, driver in self.nodes.iteritems():
|
|
|
|
try:
|
|
driver.offset = self.offset
|
|
driver.company = self.company
|
|
driver.register()
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
return True
|
|
|
|
# this is where I need to put the function to have all of my devices check in
|
|
|
|
|
|
class meshifyMain():
|
|
|
|
def __init__(self):
|
|
|
|
# add google nameserver
|
|
os.system("/bin/echo nameserver 8.8.8.8 > /etc/resolv.conf")
|
|
# make dictionary for xbee sets
|
|
|
|
# check and see if the drivers folder is there:
|
|
# if not os.path.exists("drivers"):
|
|
# #make the drivers dir
|
|
# os.makedirs("drivers")
|
|
self.MCU_ON = False
|
|
# marker or wether or not the device is a fly
|
|
self.FLY = False
|
|
self.reconnecting = False
|
|
self.mqttQ = Queue.Queue()
|
|
# get MAC address, if this breaks, you are [no longer] screwed
|
|
try:
|
|
mac = self.getHwAddr('eth0')
|
|
print("success getting mac")
|
|
except:
|
|
print("error getting mac")
|
|
try:
|
|
from uuid import getnode as get_mac
|
|
mac = get_mac()
|
|
mac = hex(mac).replace('0x', '')
|
|
n = 2
|
|
mac = [mac[i:i+n] for i in range(0, len(mac), n)]
|
|
newMac = ""
|
|
for i in mac:
|
|
newMac = newMac + i + ":"
|
|
|
|
mac = newMac[:-1]
|
|
except:
|
|
mac = "12:34:56:78:91:23"
|
|
mac = str(mac)
|
|
self.OK2Send = True
|
|
self.zigMac = mac
|
|
self.deviceUrlList = []
|
|
self.deviceVersions = {}
|
|
try:
|
|
# todo: change this to sd card if present on some devices
|
|
self.SQLQ = SQLQ.SqliteQueue(root + "sqlQueue/q2")
|
|
except:
|
|
pass
|
|
|
|
# varible for if the device is connected to the satellites.
|
|
self.SAT_COM = False
|
|
|
|
# if schedule module is there, then set up the global
|
|
try:
|
|
if sced == True:
|
|
self.schedule = schedule.schedule(
|
|
self.sets, self.mqttQ, self.getTime)
|
|
else:
|
|
self.schedule = False
|
|
except Exception as e:
|
|
print("####################")
|
|
print(e)
|
|
|
|
# try and sync the time
|
|
try:
|
|
os.system("/usr/bin/ntpdate pool.ntp.org")
|
|
os.system("/usr/sbin/ntpdate pool.ntp.org")
|
|
except:
|
|
pass
|
|
|
|
# dictionary of all the nodes attched
|
|
self.nodes = {}
|
|
|
|
mac = mac.replace(":", "")
|
|
mac = mac.upper()
|
|
print("here is the mac address")
|
|
print(mac)
|
|
|
|
# get your time offset, DST value and company id from meshify
|
|
try:
|
|
meshData = meshifyData.meshifyData(mac)
|
|
self.offset, self.dst, self.companyId = meshData.getdata()
|
|
except:
|
|
print("didn't work on api to get meshify data")
|
|
|
|
self.mac = mac
|
|
|
|
# start the debug thread:
|
|
thread.start_new_thread(self.debugThread, ())
|
|
|
|
# set up placeholder for self.mqtt
|
|
try:
|
|
clientData = {}
|
|
with open("mqtt.json", "r") as creds:
|
|
clientData = json.load(creds)
|
|
except:
|
|
with open("provision.json", "r") as prov:
|
|
with paho.Client(client_id=mac, clean_session=True) as c:
|
|
c.username_pw_set("provision", "")
|
|
c.on_message = self.on_message
|
|
c.connect(broker, port, keepalive=120)
|
|
c.subscribe("/provision/response", 0)
|
|
c.publish("/provision/request", json.dumps(json.load(prov)))
|
|
with open("mqtt.json", "r") as m:
|
|
clientData = json.load(m)
|
|
#with open("mqtt.json", "w+") as creds:
|
|
#json.dump(clientData, creds)
|
|
self.mqtt = paho.Client(client_id=clientData["clientId"], clean_session=True)
|
|
|
|
# change to false for mqtt.meshify.com
|
|
# self.mqtt.tls_insecure_set(True)
|
|
#self.mqtt.tls_set(root + "ca.crt", certfile=root + "client.crt", keyfile=root + "client.key", cert_reqs=ssl.CERT_NONE)
|
|
self.mqtt.username_pw_set(clientData["username"], clientData["password"])
|
|
|
|
print("now I'm here")
|
|
# Set up the last will and testiment to tell the system that I'm disconneted
|
|
lc = int(self.getTime()) + 30
|
|
|
|
self.deviceName = unitName + \
|
|
'_[' + self.zigMac + ':' + "00" + ':' + "00" + ']!'
|
|
self.deviceNameMain = "mainMeshify" + \
|
|
'_[' + self.zigMac + ':' + "00" + ':' + "00" + ']!'
|
|
|
|
|
|
|
|
|
|
# tell mqtt what to do on connect
|
|
self.mqtt.on_connect = self.on_connect
|
|
|
|
# tell mqtt which function to call when a message is received
|
|
self.mqtt.on_message = self.on_message
|
|
self.mqtt.on_disconnect = self.on_disconnect
|
|
|
|
# make conneciton to the MCU (only on M1 V5 right now):
|
|
|
|
try:
|
|
#from mcu import mcu_main
|
|
self.MCU_ON = False
|
|
except:
|
|
self.MCU_ON = False
|
|
|
|
try:
|
|
if self.MCU_ON == True:
|
|
print("mcu is on")
|
|
try:
|
|
print("mcu loading")
|
|
self.mcu = mcu_main.mcu_main()
|
|
|
|
# added these for ifttt actions
|
|
self.mcu.mac = self.mac
|
|
self.mcu.on_message = self.on_message
|
|
self.mcu.FLY = self.FLY
|
|
|
|
# adding this global for turning all data coming out of the device off
|
|
self.mcu.cutAllDataOff = False
|
|
|
|
print("mcu loaded")
|
|
# now see if we are a fly
|
|
flyTries = 0
|
|
self.mcu.xbeeCom(0)
|
|
self.mcu.xbee.write("+++")
|
|
time.sleep(1)
|
|
self.mcu.xbee.write("ATFR" + chr(13))
|
|
time.sleep(1)
|
|
while flyTries < 2:
|
|
#self.mcu.send_mcu("""{\"SET\": [{\"XBEECOM\": \"0\"}]}\n""")
|
|
flyTries += 1
|
|
self.mcu.xbee.read()
|
|
self.mcu.xbee.write("+++")
|
|
time.sleep(2)
|
|
self.mcu.xbee.write("ATDD" + chr(13))
|
|
time.sleep(3)
|
|
response = self.mcu.xbee.read()
|
|
if "777" in response or LORA:
|
|
print("I'm a fly")
|
|
# self.mcu.spiOn(0)
|
|
self.FLY = True
|
|
self.mcu.FLY = self.FLY
|
|
if LORA:
|
|
#self.mcu.xbee = lora_main.lora()
|
|
#self.mcu.xbee.fileTransfer = False
|
|
pass
|
|
# set the xbee to talk to the coordinator
|
|
# this needs to be working for network switching
|
|
#self.mcu.xbee.atCommandSet("DH", "0")
|
|
#self.mcu.xbee.atCommandSet("DL", "FFFF")
|
|
thread.start_new_thread(self.xbeeGetThread, ())
|
|
break
|
|
else:
|
|
self.FLY = False
|
|
except Exception as e:
|
|
print(e)
|
|
self.mcu.FLY = self.FLY
|
|
self.FLY = False
|
|
else:
|
|
print("MCU NOT ON")
|
|
self.mcu = None
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
# while True:
|
|
# time.sleep(3)
|
|
# print self.mcu.getDict()
|
|
|
|
# turn off connected LED's
|
|
if self.MCU_ON:
|
|
self.mcu.FLY = self.FLY
|
|
self.mcu.ledControl(2, 0, 0)
|
|
self.mcu.ledControl(3, 0, 0)
|
|
|
|
self.topics = []
|
|
|
|
self.topics.append("v1/device/me/telemetry")
|
|
|
|
# wait a few seconds to connect
|
|
time.sleep(5)
|
|
|
|
#####################################################
|
|
# this is the loading of the devices, if it fails, we still need main to work
|
|
# order of operations:
|
|
# 1. From API
|
|
# 2. From Text file
|
|
# 3. From previous loads pickle file
|
|
# 4. Nothing, it will only run main (not mainMeshify, just main wich can do reboot and register)
|
|
|
|
# the json data should come back from an API, for now it will come from in the root/python_firmware deviceList.txt
|
|
|
|
try:
|
|
try:
|
|
json_data = open('deviceList.txt')
|
|
data = json.load(json_data)
|
|
data = meshData.checkConfig()
|
|
if len(data) < 1:
|
|
raise ValueError('too short')
|
|
except:
|
|
json_data = open('deviceList.txt')
|
|
data = json.load(json_data)
|
|
# build a list of urls for your device driver buckets
|
|
for i in data:
|
|
print(i)
|
|
# check and see if we are running the dia, if so then kill the mcu thread running the xbee so the dia can have full access to the xbee
|
|
if i == "dia" or i == "spider":
|
|
self.mcu.xbee.runXbee = False
|
|
self.deviceUrlList.append(data[i])
|
|
print(i)
|
|
print(data[i])
|
|
|
|
pickle.dump(self.deviceUrlList, open("deviceUrls.p", "wb"))
|
|
except Exception as e:
|
|
print("####################")
|
|
print(e)
|
|
# if we can't get it from the web, look for the pickled version
|
|
try:
|
|
self.deviceUrlList = pickle.load(open("deviceUrls.p", "rb"))
|
|
except:
|
|
print("couldn't load devices from pickle")
|
|
|
|
# try and load your versions dictionary, if this can't load, then load all drivers for the first time
|
|
try:
|
|
self.deviceVersions = pickle.load(
|
|
open(root + "deviceVersions.p", "rb"))
|
|
except:
|
|
print("couldn't load devices Versions from pickle")
|
|
|
|
self.deviceList = {}
|
|
|
|
if self.FLY == False:
|
|
for i in self.deviceUrlList:
|
|
try:
|
|
print(i)
|
|
# json.load(urllib2.urlopen("http://" + i + "config.txt"))
|
|
data = json.load(urllib.urlopen(i + "config.txt"))
|
|
#data = urllib2.urlopen(("http://" + i + "config.txt"))
|
|
#data = data.read()
|
|
print(data)
|
|
#data = json.load(data)
|
|
|
|
# download the files
|
|
print("trying to download the files")
|
|
try:
|
|
if int(data["releaseVersion"]) > int(self.deviceVersions[(data["deviceName"] + "_" + data["driverId"])]):
|
|
print("new version found in repo", data["releaseVersion"])
|
|
for x in data["files"]:
|
|
print((i + data["files"][x]))
|
|
urllib.urlretrieve(
|
|
(i + data["files"][x]), ("./drivers/" + (data["files"][x])))
|
|
else:
|
|
print("we have the latest version for: " + (data["deviceName"] + "_" + data["driverId"]) + " of " + str(self.deviceVersions[(data["deviceName"] + "_" + data["driverId"])]))
|
|
except:
|
|
print("probably didn't have any files to start with, loading all files")
|
|
for x in data["files"]:
|
|
print((i + data["files"][x]))
|
|
urllib.urlretrieve(
|
|
(i + data["files"][x]), ("./drivers/" + (data["files"][x])))
|
|
|
|
dList = [data["driverFileName"].replace(
|
|
".py", ""), data["deviceName"], data["driverId"], data["releaseVersion"]]
|
|
self.deviceList[(data["deviceName"] +
|
|
"_" + data["driverId"])] = dList
|
|
print(self.deviceList)
|
|
except Exception as e:
|
|
print(e)
|
|
continue
|
|
|
|
# if our device list is still empty, try and grab the saved one
|
|
if len(self.deviceList) < 1:
|
|
# get the old device list
|
|
try:
|
|
dl = pickle.load(open("deviceList.p", "rb"))
|
|
self.deviceList = dl
|
|
print(self.deviceList)
|
|
except Exception as e:
|
|
print(e)
|
|
self.deviceList = {}
|
|
print("couldn't load deviceList from pickle")
|
|
else:
|
|
pickle.dump(self.deviceList, open("deviceList.p", "wb"))
|
|
|
|
try:
|
|
self.main = main('main', '', self.zigMac, self.mqttQ, self.mcu,
|
|
self.companyId, self.offset, self.mqtt, self.nodes, self.topics)
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
self.nodes["main"] = self.main
|
|
|
|
# filename, node name, 4 digit identifier, version number (must be an integer)
|
|
|
|
# gds deviceList
|
|
#deviceList = [ ["mainMistaway", "mainMistaway", "0000", "1"], ["gdsMT", "gdsc", "0005", "1"] ]
|
|
|
|
# gate Device List
|
|
#deviceList = [ ["mainMistaway", "mainMistaway", "0000", "1"], ["gate", "gate", "0006", "1"] ]
|
|
|
|
for device in self.deviceList:
|
|
print("trying to load: " + device)
|
|
|
|
try:
|
|
device = self.deviceList[device]
|
|
|
|
# subscribe to the device first, if it breaks, this makes it possible to fix all of this type at once
|
|
self.topics.append("v1/devices/me/attributes")
|
|
self.topics.append("v1/devices/me/rpc/request/+")
|
|
topic = str(("v1/devices/me/attributes"))
|
|
print("######", topic)
|
|
self.mqtt.subscribe(topic, 0)
|
|
topic = str(("v1/devices/me/rpc/request/+"))
|
|
print("######", topic)
|
|
self.mqtt.subscribe(topic, 0)
|
|
|
|
# import the file from the devices folder
|
|
imported_module = __import__("drivers." + str(device[0]))
|
|
# import the code from the device driver
|
|
fileImport = getattr(imported_module, str(device[0]))
|
|
# import the driver class from the file
|
|
funct = getattr(fileImport, "start")
|
|
# start this instance and add it to the devices dictionary
|
|
self.nodes[(str(device[1]) + "_" + str(device[2]))] = funct(name=str(device[1]), number=str(device[2]), mac=self.zigMac,
|
|
Q=self.mqttQ, mcu=self.mcu, companyId=self.companyId, offset=self.offset, mqtt=self.mqtt, Nodes=self.nodes)
|
|
|
|
# add name and version to a dictionary for pickling
|
|
self.deviceVersions[(str(device[1]) + "_" + str(device[2]))
|
|
] = self.nodes[(str(device[1]) + "_" + str(device[2]))].version
|
|
pickle.dump(self.deviceVersions, open(
|
|
root + "deviceVersions.p", "wb"))
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
lc = self.getTime()
|
|
value = "Failed Loading: " + \
|
|
str(device[2]) + " on startup with error: " + str(e)
|
|
msg = """[ { "value":"%s", "msgId":"%s" } ]""" % ((value), "1")
|
|
topic = "meshify/errors/"
|
|
self.mqttQ.put([topic, str(msg), 2])
|
|
print(e)
|
|
|
|
if self.FLY == False:
|
|
print("made it to here, not a fly")
|
|
# start logging data!!!
|
|
self.reconnecting = True
|
|
thread.start_new_thread(self.sqlPoolThread, ())
|
|
|
|
# connect to broker
|
|
#thread.start_new_thread(self.connect_thread, ())
|
|
while True:
|
|
try:
|
|
self.connect_to_broker()
|
|
self.reconnecting = False
|
|
try:
|
|
os.system("/usr/bin/ntpdate pool.ntp.org")
|
|
os.system("/usr/sbin/ntpdate pool.ntp.org")
|
|
os.system("ntpdate pool.ntp.org")
|
|
except:
|
|
pass
|
|
break
|
|
except:
|
|
print("didn't work this time")
|
|
time.sleep(30)
|
|
|
|
# tell the MQTT client to run forever!!
|
|
print("made it here")
|
|
while True:
|
|
print("##### here is the connection status #### ", str(self.mqtt._state))
|
|
try:
|
|
if not self.FLY:
|
|
print(self.mqtt.loop())
|
|
if self.MCU_ON:
|
|
if self.mcu.cutAllDataOff:
|
|
print("All Data is Being cut off, no outbound alloud")
|
|
time.sleep(5)
|
|
continue
|
|
|
|
if not self.mqttQ.empty(): # or self.SQLQ.getLen() > 0:
|
|
if str(self.mqtt._state) == "1" or self.FLY == True:
|
|
|
|
try:
|
|
print(self.SQLQ.getLen())
|
|
if self.SQLQ.getLen() > 0:
|
|
loopCount = 0
|
|
while self.SQLQ.getLen() > 0:
|
|
loopCount += 1
|
|
if loopCount > 20:
|
|
loopCount = 0
|
|
if not self.FLY:
|
|
print(self.mqtt.loop())
|
|
val = self.SQLQ.popleft()
|
|
if not self.FLY:
|
|
resp = self.mqtt.publish(
|
|
val[0], val[1], val[2])
|
|
|
|
else:
|
|
if val[0].split("/")[1] == "db":
|
|
xeebVal = json.dumps(
|
|
json.loads(val[1])[0]["value"])
|
|
if xeebVal.startswith('"') and xeebVal.endswith('"'):
|
|
xeebVal = xeebVal[1:-1]
|
|
upld = val[0].split(
|
|
"/")[3] + "/" + val[0].split("/")[4] + "/" + val[0].split("/")[5] + "/" + xeebVal
|
|
self.xbeeSend(upld)
|
|
time.sleep(.5)
|
|
else:
|
|
respId = (''.join(random.choice(
|
|
'0123456789ABCDEF') for i in range(4)))
|
|
self.xbeeSend(
|
|
"%%" + val[0] + "%%" + json.dumps(json.loads(val[1])[0]["value"]) + "%%")
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
print("no SQL Queue on this device")
|
|
|
|
try:
|
|
val = self.mqttQ.get(block=False, timeout=1)
|
|
# print "Outputting: ", val
|
|
if not self.FLY:
|
|
resp = self.mqtt.publish(
|
|
val[0], val[1], val[2])
|
|
elif self.mcu.xbee.fileTransfer == True:
|
|
# if we are sending a file, put this data point back in the Q
|
|
self.mqttQ.put(val)
|
|
time.sleep(3)
|
|
continue
|
|
else:
|
|
if val[0].split("/")[1] == "db":
|
|
xeebVal = json.dumps(
|
|
json.loads(val[1])[0]["value"])
|
|
if xeebVal.startswith('"') and xeebVal.endswith('"'):
|
|
xeebVal = xeebVal[1:-1]
|
|
upld = val[0].split(
|
|
"/")[3] + "/" + val[0].split("/")[4] + "/" + val[0].split("/")[5] + "/" + xeebVal
|
|
self.xbeeSend(upld)
|
|
else:
|
|
self.xbeeSend(
|
|
"%%" + val[0] + "%%" + json.dumps(json.loads(val[1])[0]["value"]) + "%%")
|
|
time.sleep(2)
|
|
# print "####### here is the response"
|
|
# make a dictionary of response codes xbee
|
|
# print resp
|
|
except:
|
|
print("Q had an error")
|
|
time.sleep(1)
|
|
loopCount = 0
|
|
while self.mqttQ.qsize() > 20:
|
|
loopCount += 1
|
|
if loopCount > 20:
|
|
loopCount = 0
|
|
if not self.FLY:
|
|
print(self.mqtt.loop())
|
|
try:
|
|
val = self.mqttQ.get(block=False, timeout=1)
|
|
# print "Outputting: ", val
|
|
|
|
if not self.FLY:
|
|
resp = self.mqtt.publish(
|
|
val[0], val[1], val[2])
|
|
elif self.mcu.xbee.fileTransfer == True:
|
|
# if we are sending a file, put this data point back in the Q
|
|
self.mqttQ.put(val)
|
|
time.sleep(3)
|
|
continue
|
|
else:
|
|
if val[0].split("/")[1] == "db":
|
|
xeebVal = json.dumps(
|
|
json.loads(val[1])[0]["value"])
|
|
if xeebVal.startswith('"') and xeebVal.endswith('"'):
|
|
xeebVal = xeebVal[1:-1]
|
|
upld = val[0].split(
|
|
"/")[3] + "/" + val[0].split("/")[4] + "/" + val[0].split("/")[5] + "/" + xeebVal
|
|
self.xbeeSend(upld)
|
|
|
|
else:
|
|
self.xbeeSend(
|
|
"%%" + val[0] + "%%" + json.dumps(json.loads(val[1])[0]["value"]) + "%%")
|
|
time.sleep(2)
|
|
|
|
except:
|
|
print("Q had an error")
|
|
time.sleep(1)
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
time.sleep(10)
|
|
if self.reconnecting == False:
|
|
self.recon()
|
|
time.sleep(.5)
|
|
|
|
def connect_thread(self):
|
|
while True:
|
|
try:
|
|
print("####### connecting to the broker ########")
|
|
self.connect_to_broker()
|
|
|
|
except Exception as e:
|
|
print((str(e)))
|
|
print("didn't work to connect, restarting....")
|
|
os.system('/root/reboot')
|
|
|
|
def connect_to_broker(self):
|
|
|
|
if self.companyId == "1":
|
|
meshData = meshifyData.meshifyData(self.mac)
|
|
self.offset, self.dst, self.companyId = meshData.getdata()
|
|
|
|
self.mqtt.connect(broker, port, keepalive=120)
|
|
self.topic_sub()
|
|
|
|
# tell the MQTT client to run forever!!
|
|
# self.mqtt.loop_forever()
|
|
|
|
def on_disconnect(self, mosq, userdata, rc):
|
|
print("################ DISCONECCTED #################")
|
|
|
|
# turn off connected LED
|
|
if self.MCU_ON:
|
|
self.mcu.ledControl(2, 0, 0)
|
|
|
|
self.recon()
|
|
|
|
def connect_check(self):
|
|
# this funtion checks to see how many times its tried to reconnect in the 3 minutes that it goes to sleep
|
|
# if it wakes up and you are on the same attempt, then its froze and needs to reboot
|
|
local_count = self.count
|
|
time.sleep(180)
|
|
if local_count == self.count:
|
|
# Dont reboot if connected to SAT
|
|
if self.SAT_COM == True:
|
|
pass
|
|
else:
|
|
os.system('/root/reboot')
|
|
|
|
def sqlPoolThread(self):
|
|
|
|
# while spooling the data I am going to attempt a handshake with the SkyWave satellites
|
|
# handshake data will include my mac address
|
|
# the web will return my current UTC time, which by the time I get it, it will be off by a few seconds, but whos counting ;)
|
|
# if it connects, it will set a variable called SAT_COM to True, by way of the main device
|
|
print("starting up sat connection")
|
|
|
|
# start a Queue for the sending up of data to the SATS
|
|
satQ = Queue.Queue()
|
|
if SAT == True and self.FLY == False:
|
|
thread.start_new_thread(
|
|
SkyWaveDataAPI.skywave, (self.sets, self.mac, self.stateData, satQ, self.mcu))
|
|
|
|
# wait 1 minute to see if we connect to the SATs
|
|
time.sleep(60)
|
|
try:
|
|
while self.reconnecting == True:
|
|
val = self.mqttQ.get()
|
|
try:
|
|
if self.SQLQ.getLen() > 5000:
|
|
# delete oldest value
|
|
trash = self.SQLQ.popleft()
|
|
|
|
except:
|
|
pass
|
|
if self.SAT_COM == True:
|
|
print("sending up data to sats")
|
|
satQ.put(val)
|
|
else:
|
|
print("storing up data for later 3g connection")
|
|
try:
|
|
self.SQLQ.append(val)
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
def recon(self):
|
|
self.reconnecting = True
|
|
thread.start_new_thread(self.sqlPoolThread, ())
|
|
count = 0
|
|
while True:
|
|
|
|
if count > 2000:
|
|
if self.SAT_COM == True:
|
|
count = 0
|
|
else:
|
|
break
|
|
|
|
count += 1
|
|
print(count)
|
|
try:
|
|
self.count = count
|
|
thread.start_new_thread(self.connect_check, ())
|
|
self.mqtt.reconnect()
|
|
self.count = 0
|
|
self.reconnecting = False
|
|
break
|
|
except:
|
|
print("couldn't reconnect, retrying in 30 seconds")
|
|
os.system("/bin/echo nameserver 8.8.8.8 > /etc/resolv.conf")
|
|
os.system("/sbin/ifup 3g")
|
|
time.sleep(30)
|
|
|
|
if count > 2000 and not self.FLY:
|
|
# don't reboot if connected to SAT
|
|
print("rebooting now")
|
|
os.system('/root/reboot')
|
|
|
|
def on_connect(self, mosq, userdata, rc):
|
|
|
|
# turn connected LED
|
|
if self.MCU_ON:
|
|
self.mcu.ledControl(2, 1, 0)
|
|
self.mcu.ledControl(3, 0, 0)
|
|
else:
|
|
print("on_connect() MCU_OFF = False!!!!!")
|
|
|
|
# stop using sat data
|
|
self.SAT_COM = False
|
|
|
|
# let the watchdog know we are not on SAT anymore
|
|
os.system('/bin/echo False > /root/SAT')
|
|
|
|
# wait a few seconds for the connection to be made solid
|
|
time.sleep(4)
|
|
|
|
# set the channel connected to true
|
|
lc = self.getTime()
|
|
|
|
csplit = re.split(r"(.*?)_\[(.*?)\]", self.deviceName)
|
|
nodeTypeName = csplit[1]
|
|
uniqueID = csplit[2]
|
|
company = "194"
|
|
|
|
topic = 'meshify/db/%s/%s/%s/%s/%s' % (company,
|
|
"_", nodeTypeName, uniqueID, "connected")
|
|
msg = """[{"value":"%s"}]""" % ("true")
|
|
self.mqttQ.put([topic, msg, 2])
|
|
|
|
# set the network to 3g
|
|
lc = self.getTime()
|
|
topic = 'meshify/db/%s/%s/%s/%s/%s' % (company,
|
|
"_", nodeTypeName, uniqueID, "net")
|
|
msg = """[{"value":"%s"}]""" % ("3g")
|
|
self.mqttQ.put([topic, msg, 2])
|
|
|
|
print((" ############### Connection returned " +
|
|
str(rc) + " ###############"))
|
|
self.topic_sub()
|
|
|
|
def topic_sub(self):
|
|
for topic in self.topics:
|
|
print(topic)
|
|
self.mqtt.subscribe(topic, 0)
|
|
|
|
def sets(self, msg, sch=False):
|
|
entireMsg = msg
|
|
# [{"user":"demo@meshify.com","mac":"000CE373293D","company":"188","payload":{"name":"wipom_[00:0c:e3:73:29:3d:00:21]!.do2","value":"1","expires":"1389369695"},"msgId":4478}]
|
|
#{"driver.function": "value", "msgId": 1234}
|
|
print("I got the set")
|
|
print(msg)
|
|
try:
|
|
data = json.loads(msg)
|
|
keys = data.keys()
|
|
msgId = 0
|
|
for x in keys:
|
|
if x != "msgId":
|
|
name = x
|
|
if x == "msgId":
|
|
msgId = data["msgId"]
|
|
value = data[name]
|
|
|
|
print(name, value)
|
|
|
|
#name = 'tankalarms.water_spt'
|
|
# grab the 4 digit unique device code from the end of the MAC address
|
|
|
|
n = name.split('.')
|
|
channel = n[1]
|
|
n = n[0]
|
|
|
|
try:
|
|
# if the first part of the zigbee mac address is legit, meaning it comes from digi
|
|
# then I need to treat this like a mesh node and send it to the dia
|
|
# This is only for the SPIDER's Dia Nodes
|
|
# the best check is to see if the addresses are derived from the same address
|
|
if name.split('.')[0].split("_")[1].replace("[", "").replace(":", "").replace("]!", "")[:-10].upper() == "0013A2":
|
|
print("found an xbee")
|
|
#setData = """<data><channel_set name="%s" value="%s"/></data>$$$%s""" % (name, value, msgId)
|
|
setData = {}
|
|
setData['name'] = name
|
|
setData['value'] = value
|
|
setData['id'] = msgId
|
|
print(setData)
|
|
self.main.meshQ.put(setData)
|
|
return
|
|
except:
|
|
print("couldn't determine if there was an xbee")
|
|
|
|
if n == "main":
|
|
if channel == "SAT":
|
|
print("got ping from sat cloud app, this mean we have a connection")
|
|
try:
|
|
if float(value) > 1422910000:
|
|
print("SAT CONNECTED!!!")
|
|
self.SAT_COM = True
|
|
# turn connected LED to amber
|
|
if self.MCU_ON:
|
|
self.mcu.ledControl(3, 1, 0)
|
|
self.mcu.ledControl(2, 0, 0)
|
|
# send connected = True
|
|
lc = self.getTime()
|
|
topic = 'meshify/db/%s/%s/%s/%s' % (
|
|
self.companyId, self.mac, self.deviceName, "connected")
|
|
msg = """[ { "value":"%s", "timestamp":"%s" } ]""" % (
|
|
"True", str(lc))
|
|
self.mqttQ.put([topic, msg, 2])
|
|
|
|
# set the network to sat
|
|
lc = self.getTime()
|
|
topic = 'meshify/db/%s/%s/%s/%s' % (
|
|
self.companyId, self.mac, self.deviceName, "net")
|
|
msg = """[ { "value":"%s", "timestamp":"%s" } ]""" % (
|
|
"sat", str(lc))
|
|
self.mqttQ.put([topic, msg, 2])
|
|
|
|
# let the watchdog know if we are on SAT
|
|
os.system('/bin/echo True > /root/SAT')
|
|
except:
|
|
print("didn't send the right date")
|
|
nodeName = "main"
|
|
nodeNumber = ""
|
|
|
|
else:
|
|
#m = n
|
|
# m = m.split('_')
|
|
#m = re.split(r"(.*?)_\[(.*?)\]", m)
|
|
# nodeName = m[0]
|
|
nodeName = n
|
|
#n = n.replace(']!', '')
|
|
#n = n[-5:]
|
|
#nodeNumber = n.replace(':', '')
|
|
nodeNumber = "_" + "0199" #nodeNumber
|
|
except:
|
|
print("not valid JSON")
|
|
return
|
|
|
|
# check and see if you are setting the scheduler
|
|
if channel.startswith("sch-"):
|
|
print("data now being sent to the scheduler")
|
|
try:
|
|
if self.schedule != False:
|
|
self.schedule.message(channel, json.loads(entireMsg))
|
|
return
|
|
except:
|
|
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
|
print("BAD JSON")
|
|
return
|
|
|
|
# this grabs the class for the driver for the node: #this should be called className
|
|
funcName = nodeName + nodeNumber
|
|
# this grabs the method for that channel inside of the driver for that node:
|
|
funcChan = nodeName + '_' + channel
|
|
print(funcName)
|
|
# try:
|
|
# # if nodes[funcName] != undefined
|
|
# #channelCallback = getattr(nodes[funcName], funcChan)
|
|
# #success = channelCallback(channel, value)
|
|
# func = getattr(self, funcName)
|
|
# except:
|
|
# print 'no Set callback found for channel: ' + funcName
|
|
# else:
|
|
try:
|
|
# classFunc = getattr(func, funcChan) #func(value)
|
|
#success = classFunc(channel, value)
|
|
|
|
# first try a specific callback set, the fundtion will look like: deviceName_0000
|
|
try:
|
|
print("trying to find callback for:")
|
|
print(funcChan)
|
|
channelCallback = getattr(self.nodes[funcName], funcChan)
|
|
success = channelCallback(channel, value)
|
|
except:
|
|
print("looking for genericSet")
|
|
# now try a generic one, that looks like self.genericSet(self, channel, value, UnitNumber) Unit number is the second to last 2 digits of the tech name
|
|
channelCallback = getattr(self.nodes[funcName], "genericSet")
|
|
try:
|
|
success = channelCallback(
|
|
channel, value, nodeNumber[1:3], nodeNumber[1:])
|
|
except:
|
|
success = channelCallback(channel, value, nodeNumber[1:3])
|
|
|
|
#csplit = re.split(r"(.*?)_\[(.*?)\]", self.deviceNameMain)
|
|
#nodeTypeName = csplit[1]
|
|
#uniqueID = csplit[2]
|
|
#company = "194"
|
|
|
|
if success == True:
|
|
if int(msgId) == 0:
|
|
return 0
|
|
if sch == False:
|
|
msg = json.dumps({"value": True})
|
|
topic = "v1/devices/me/rpc/response/" + msgId
|
|
self.mqttQ.put([topic, str(msg), 2])
|
|
|
|
else:
|
|
return 0
|
|
|
|
else:
|
|
if sch == False:
|
|
msg = json.dumps({"value": False})
|
|
topic = "v1/devices/me/rpc/response/" + msgId
|
|
self.mqttQ.put([topic, str(msg), 2])
|
|
|
|
else:
|
|
return 1
|
|
except:
|
|
if int(msgId) == 0:
|
|
return 2
|
|
if sch == False:
|
|
msg = json.dumps({"value": False})
|
|
topic = "v1/devices/me/rpc/response/" + msgId
|
|
self.mqttQ.put([topic, str(msg), 2])
|
|
print('no Set callback found for channel: ' + funcName)
|
|
|
|
else:
|
|
return 2
|
|
|
|
# function to be called when a message is received
|
|
|
|
def handle_message(self, topic, payload, qos):
|
|
try:
|
|
|
|
csplit = re.split(r"(.*?)_\[(.*?)\]", self.deviceNameMain)
|
|
nodeTypeName = csplit[1]
|
|
uniqueID = csplit[2]
|
|
company = "194"
|
|
|
|
print(("Message received on topic "+topic+" with QoS "+str(qos)))
|
|
topics = topic.split("/")
|
|
if topics[1] == "files" and topics[4] == "write":
|
|
self.OK2Send = False
|
|
path = topics[5]
|
|
path = path.replace("$", "/")
|
|
print(path)
|
|
with open(path, 'wb') as fd:
|
|
fd.write(payload)
|
|
fd.close()
|
|
print("file written")
|
|
# update the channel mainMistaway_files, a dummy channel for keeping track of file transactions
|
|
lc = self.getTime()
|
|
topic = 'meshify/db/%s/%s/%s/%s/%s' % (
|
|
company, "_", nodeTypeName, uniqueID, "files")
|
|
msg = """[ { "value":"%s" } ]""" % (
|
|
(str(self.mac) + " File Written: " + path))
|
|
self.mqttQ.put([topic, msg, 2])
|
|
elif topics[1] == "files" and topics[4] == "get":
|
|
|
|
self.OK2Send = False
|
|
path = topics[5]
|
|
mqttpath = path
|
|
path = path.replace("$", "/")
|
|
print(path)
|
|
f = open(path, 'rb')
|
|
byteArray = f.read()
|
|
#byteArray = bytes(byteArray)
|
|
topic = 'meshify/get/%s/%s/%s/%s' % (
|
|
company, "_", uniqueID, mqttpath)
|
|
msg = byteArray
|
|
self.mqtt.publish(topic, msg, 0)
|
|
f.close()
|
|
print("message sent on topic: ", topic)
|
|
|
|
# update the channel mainMistaway_files, a dummy channel for keeping track of file transactions
|
|
lc = self.getTime()
|
|
topic = 'meshify/db/%s/%s/%s/%s/%s' % (
|
|
company, "_", nodeTypeName, uniqueID, "files")
|
|
msg = """[ { "value":"%s" } ]""" % (
|
|
(str(self.mac) + " File Sent: " + path))
|
|
self.mqttQ.put([topic, msg, 2])
|
|
elif topics[1] == "files" and topics[4] == "delete" and payload == "delete":
|
|
path = topics[5]
|
|
path = path.replace("$", "/")
|
|
val = "Success Deleting "
|
|
try:
|
|
os.remove(path)
|
|
except OSError as e: # if failed, report it back to the user ##
|
|
val = "Error Deleting "
|
|
print(("Error: %s - %s." % (e.filename, e.strerror)))
|
|
|
|
# update the channel mainMistaway_files, a dummy channel for keeping track of file transactions
|
|
lc = self.getTime()
|
|
topic = 'meshify/db/%s/%s/%s/%s/%s' % (
|
|
company, "_", nodeTypeName, uniqueID, "files")
|
|
msg = """[ { "value":"%s" } ]""" % ((val + path))
|
|
self.mqttQ.put([topic, msg, 2])
|
|
elif topics[1] == "sets":
|
|
self.sets(payload)
|
|
self.OK2Send = True
|
|
except Exception as e:
|
|
print(e)
|
|
self.OK2Send = True
|
|
print("error understanding the mqtt message")
|
|
|
|
def on_message(self, mosq, obj, msg):
|
|
|
|
try:
|
|
print("!!!!!!! ON MESSAGE !!!!!!!")
|
|
print(msg.topic)
|
|
print(msg.payload)
|
|
if "rpc" in msg.topic:
|
|
payload = {}
|
|
payload["msgId"] = msg.topic.split("/")[-1]
|
|
jpayload = json.loads(msg.payload)
|
|
payload[jpayload["method"]] = jpayload["params"]["value"]
|
|
msg.payload = json.dumps(payload)
|
|
if "provision" in msg.topic:
|
|
with open("mqtt.json", "w+") as m:
|
|
newCreds = {
|
|
"clientId": self.mac,
|
|
"username": msg.payload["credentialsValue"],
|
|
"password": ""
|
|
}
|
|
json.dumps(newCreds)
|
|
self.sets(msg.payload)
|
|
except Exception as e:
|
|
print(e)
|
|
print("HELP HELP HELP")
|
|
"""
|
|
try:
|
|
print(msg)
|
|
|
|
csplit = re.split(r"(.*?)_\[(.*?)\]", self.deviceNameMain)
|
|
nodeTypeName = csplit[1]
|
|
uniqueID = csplit[2]
|
|
company = "194"
|
|
|
|
m1ID = uniqueID[:18] + "00:30"
|
|
rigpumpID = uniqueID[:18] + "01:99"
|
|
plevelID = uniqueID[:18] + "01:30"
|
|
flowID = uniqueID[:18] + "01:40"
|
|
subID = uniqueID[:18] + "02:10"
|
|
liteID = uniqueID[:18] + "02:30"
|
|
ippID = uniqueID[:18] + "00:90"
|
|
|
|
# if the message has either a device name or the mac address of this unit then send to handle_message if not send to dia
|
|
# if the name isn't hex, then its an ascii group set
|
|
try:
|
|
num = int(msg.topic.split("/")[2], 16)
|
|
is_hex = True
|
|
except:
|
|
is_hex = False
|
|
|
|
try:
|
|
# if the device is in the xbeeQ lookup dictionary, then pass it there
|
|
devName = json.loads(msg.payload)[
|
|
0]["payload"]["name"].split(".")[0]
|
|
if devName in self.mcu.xbees:
|
|
# this is an xbee node running the dia
|
|
xbeeSet = self.mcu.xbees[devName]
|
|
xbeeSet.put([msg.topic, msg.payload])
|
|
return
|
|
except Exception as e:
|
|
print(e)
|
|
print("error parsing set for xbee")
|
|
# case 1, the message is meant for me or I'm a fly
|
|
# case 2, the company ID is a number, not a word, try the set to the xbee again i guess??
|
|
# case 3, the compnay id was actually a group, send it to both the
|
|
if msg.topic.split("/")[3] == uniqueID.upper() or msg.topic.split("/")[3] == m1ID.upper() or msg.topic.split("/")[3] == rigpumpID.upper() or msg.topic.split("/")[3] == plevelID.upper() or msg.topic.split("/")[3] == flowID.upper() or msg.topic.split("/")[3] == subID.upper() or msg.topic.split("/")[3] == liteID.upper() or msg.topic.split("/")[3] == ippID.upper() or self.FLY == True:
|
|
thread.start_new_thread(
|
|
self.handle_message, (msg.topic, msg.payload, msg.qos))
|
|
elif is_hex:
|
|
xbeeSet = self.mcu.xbees[msg.topic.split("/")[3]]
|
|
xbeeSet.put([msg.topic, msg.payload])
|
|
else:
|
|
# this is a group, so set both
|
|
thread.start_new_thread(
|
|
self.handle_message, (msg.topic, msg.payload, msg.qos))
|
|
xbeeSet = self.mcu.xbees[msg.topic.split("/")[3]]
|
|
xbeeSet.put([msg.topic, msg.payload])
|
|
except:
|
|
pass"""
|
|
|
|
# this retrieves the MAC address from the ethernet card
|
|
|
|
def getHwAddr(self, ifname):
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
info = fcntl.ioctl(s.fileno(), 0x8927,
|
|
struct.pack('256s', ifname[:15]))
|
|
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
|
|
|
|
def stateData(self):
|
|
return self.SAT_COM, self.reconnecting
|
|
|
|
def getTime(self):
|
|
return str(int(time.time() + int(self.offset)))
|
|
# Here is the spot for all of your channel set callbacks
|
|
# Callbacks are to be writen with the following nameing scheme:
|
|
# deviceName_DeviceId_ChannelName
|
|
# the function will take in the new value it is getting set to
|
|
# for any action to take place on that channel set you must define a callback
|
|
# with the name defined by the nameing scheme above.
|
|
|
|
def debugThread(self):
|
|
|
|
# this thread is reading the system output of the core as its runs and publishes it to
|
|
# the topic: meshify/debug/macaddress
|
|
|
|
# TODO Use iMist2 rset tracing module
|
|
|
|
try:
|
|
print('Number of arguments:', len(sys.argv), 'arguments.')
|
|
if str(sys.argv[1]).lower().strip() == "debug=true" or str(sys.argv[1]).lower().strip() == "debug = true" or str(sys.argv[1]).lower().strip() == "true":
|
|
try:
|
|
if len(str(sys.argv[2]).lower().strip()) > 2:
|
|
fileLocation = str(sys.argv[2]).lower().strip()
|
|
else:
|
|
fileLocation = "/tmp/main.log"
|
|
except:
|
|
fileLocation = "/tmp/main.log"
|
|
|
|
file = open(fileLocation, 'r+')
|
|
while 1:
|
|
where = file.tell()
|
|
line = file.readline()
|
|
if not line:
|
|
file.seek(where)
|
|
file.truncate(0)
|
|
time.sleep(1)
|
|
file.seek(0)
|
|
else:
|
|
topic = "meshify/debug/" + self.mac
|
|
msg = filter(
|
|
lambda x: x in string.printable, str(line))
|
|
self.mqttQ.put([topic, msg, 0])
|
|
except Exception as e:
|
|
print("debug error")
|
|
print(e)
|
|
|
|
def xbeeSend(self, data):
|
|
|
|
respId = (''.join(random.choice('0123456789ABCDEF') for i in range(4)))
|
|
data = data + respId + "$"
|
|
count = 0
|
|
|
|
while True and self.mcu.xbee.fileTransfer == False:
|
|
if count > 5:
|
|
print("failed getting response after 3 tries")
|
|
if self.xbeeConnected == True:
|
|
self.xbeeConnected = False
|
|
# broadcast to coordinator
|
|
#self.mcu.xbee.atCommandSet("DH", "0")
|
|
#self.mcu.xbee.atCommandSet("DL", "FFFF")
|
|
# turn off connected LED
|
|
if self.MCU_ON:
|
|
self.mcu.ledControl(2, 0, 0)
|
|
self.mcu.ledControl(1, 0, 0)
|
|
# let the watchdog know we are not connected to the SPIDER
|
|
os.system('/bin/echo False > /root/XBEE')
|
|
return False
|
|
count += 1
|
|
try:
|
|
self.mcu.xbee.write(base64.b64encode(data.encode('utf-8')))
|
|
except Exception as e:
|
|
print("error writing xbee to gateway")
|
|
print(e)
|
|
inner_count = 0
|
|
while True and self.mcu.xbee.fileTransfer == False:
|
|
inner_count += 1
|
|
time.sleep(.5)
|
|
if respId in self.xbeeResponseList:
|
|
print("id found!!!")
|
|
if self.xbeeConnected == False:
|
|
self.xbeeConnected = True
|
|
# turn connected LED
|
|
if self.MCU_ON:
|
|
self.mcu.ledControl(2, 1, 0)
|
|
self.mcu.ledControl(1, 1, 0)
|
|
# let the watchdog know we are connected to the SPIDER
|
|
os.system('/bin/echo True > /root/XBEE')
|
|
return True
|
|
elif inner_count > 12:
|
|
print("no response found")
|
|
break
|
|
|
|
def xbeeGetThread(self):
|
|
# build a list of last 20 responses ie: if id in listofIds then OK
|
|
# when the ID's start populating, turn connected on!! LED
|
|
self.xbeeResponseList = []
|
|
self.xbeeConnected = False
|
|
data = ""
|
|
while True:
|
|
if self.mcu.xbee.fileTransfer == True:
|
|
time.sleep(5)
|
|
continue
|
|
else:
|
|
try:
|
|
newData = self.mcu.xbee.read()
|
|
if newData != "":
|
|
data += newData
|
|
print(data)
|
|
if "$$" in data:
|
|
list_of_sets = data.split("$$")
|
|
if len(list_of_sets[len(list_of_sets) - 1]) < 1:
|
|
data = ""
|
|
del list_of_sets[-1]
|
|
else:
|
|
data = list_of_sets[len(list_of_sets) - 1]
|
|
del list_of_sets[-1]
|
|
for item in list_of_sets:
|
|
if len(item) == 4:
|
|
print("new response id", item)
|
|
self.xbeeResponseList.append(item)
|
|
if len(self.xbeeResponseList) > 20:
|
|
self.xbeeResponseList.pop(0)
|
|
continue
|
|
print("we have a complete message")
|
|
topic = item.split("%%")[1]
|
|
payload = item.split("%%")[2]
|
|
self.handle_message(topic, payload, 1)
|
|
time.sleep(2)
|
|
else:
|
|
time.sleep(.5)
|
|
continue
|
|
|
|
except Exception as e:
|
|
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
|
|
print("xbee read error")
|
|
print(e)
|
|
time.sleep(1)
|
|
|
|
|
|
def startMain():
|
|
try:
|
|
test = meshifyMain()
|
|
except:
|
|
pass
|
|
|
|
|
|
startMain()
|