Files
ThingsBoard/meshifyDrivers/M1/m1-7.py
2024-11-12 08:40:28 -06:00

3218 lines
153 KiB
Python

import types
import traceback
import binascii
import threading
import time
import thread
import os
import struct
import sys
import serial
import minimalmodbus
import minimalmodbusM1
import pickle
import json
import vpn
import subprocess
import socket
import copy
try:
from xmodem import XMODEM
except:
pass
import zlib
from device_base import deviceBase
try:
from modbus import modbus_rtu
except:
pass
from struct import *
try:
import modbus
from modbus import defines as cst
from modbus import modbus_tcp
except:
print "no tcp modbus"
try:
from pycomm.ab_comm.clx import Driver as ClxDriver
from pycomm.ab_comm.slc import Driver as SlcDriver
except:
print "no Ethernet/IP support"
try:
import logger
except:
print "Missing logger"
pass
_NUMBER_OF_BYTES_PER_REGISTER = 2
analogMap = {
"uval":"units_high",
"lval":"units_low",
"uvolts":"volts_high",
"lvolts":"volts_low",
"low":"alarm_low",
"high":"alarm_high",
"Not Yet":"action_high",
"N/A":"action_low",
"change":"change_amount",
"minrep":"min_period",
"grp":"grp",
"mult":"multiplier",
"int":"interval",
"ch":"change_amount"
}
analogToChannelMap = {
"units_high":"uval",
"units_low":"lval",
"volts_high":"uvolts",
"volts_low":"lvolts",
"alarm_low":"low",
"alarm_high":"high",
"change_amount":"change",
"min_period":"minrep",
"grp":"grp"
}
class start(threading.Thread, deviceBase):
"""\
This class extends one of our base classes and is intended as an
example of a concrete, example implementation, but it is not itself
meant to be included as part of our developer API. Please consult the
base class documentation for the API and the source code for this file
for an example implementation.
"""
# here are the setting defaults
DEF_HEXDEC = True
DEF_EOLN = None
DEF_CHARTOUT = 2.0
# a sanity value to prevent an infinite rcv_buffer creation
DEF_MAX_READ = 1000
def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None, companyId=None, offset=None, mqtt=None, Nodes=None):
threading.Thread.__init__(self)
deviceBase.__init__(self, name=name, number=number, mac=mac, Q=Q, mcu=mcu, companyId=companyId, offset=offset, mqtt=mqtt, Nodes=Nodes)
self.daemon = True
self.vpn = vpn.vpn()
self.modbusInterfaces = {}
self.lock = threading.Lock()
self.analogLock = threading.Lock()
self.flyFileLocation = "/root/python_firmware/drivers/output.py"
self.lastData = ""
self.fileLoading = False
#self.mcu.digitalOut1(str(1))
#self.mcu.digitalOut2(str(1))
#self.mcu.digitalOut3(str(1))
#self.mcu.digitalOut4(str(1))
self.version = "37"
self.sysReboot = False
#check and see if we are going to update the mcu code
if os.path.isfile('/root/python_firmware/drivers/gsmgps.py'):
print "found new gsmgps file"
os.system("/bin/mv -f /root/python_firmware/drivers/gsmgps.py /root/python_firmware/mcu/gsmgps.py")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/gsmgps.py")
os.system("/bin/rm -f /root/python_firmware/drivers/gsmgps.pyc")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/mcu_main.py'):
print "found new mcu_main file"
os.system("/bin/mv -f /root/python_firmware/drivers/mcu_main.py /root/python_firmware/mcu/mcu_main.py")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/mcu_main.py")
os.system("/bin/rm -f /root/python_firmware/drivers/mcu_main.pyc")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/device_base.py'):
print "found new device_base file"
os.system("/bin/mv -f /root/python_firmware/drivers/device_base.py /root/python_firmware/device_base.py")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/device_base.py")
os.system("/bin/rm -f /root/python_firmware/drivers/device_base.pyc")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/vpn.py'):
print "found new vpn file"
os.system("/bin/mv -f /root/python_firmware/drivers/vpn.py /root/python_firmware/vpn.py")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/vpn.py")
os.system("/bin/rm -f /root/python_firmware/drivers/vpn.pyc")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/gsmWatchdog.py'):
print "found new gsmWatchdog file"
os.system("/bin/mv -f /root/python_firmware/drivers/gsmWatchdog.py /root/gsmWatchdog.py")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/gsmWatchdog.py")
os.system("/bin/rm -f /root/python_firmware/drivers/gsmWatchdog.pyc")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/deviceList.txt'):
print "found new deviceList.txt file"
os.system("/bin/mv -f /root/python_firmware/drivers/deviceList.txt /root/python_firmware/deviceList.txt")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/deviceList.txt")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/deviceUrls.p'):
print "found new deviceUrls.p file"
os.system("/bin/mv -f /root/python_firmware/drivers/deviceUrls.p /root/python_firmware/deviceUrls.p")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/deviceUrls.p")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/deviceVersions.p'):
print "found new deviceVersions.p file"
os.system("/bin/mv -f /root/python_firmware/drivers/deviceVersions.p /root/python_firmware/deviceVersions.p")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/deviceVersions.p")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/meshifyData.py'):
print "found new meshifyData.py file"
os.system("/bin/mv -f /root/python_firmware/drivers/meshifyData.py /root/python_firmware/meshifyData/meshifyData.py")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/meshifyData.py")
os.system("/bin/rm -f /root/python_firmware/drivers/meshifyData.pyc")
self.sysReboot = True
if os.path.isfile('/root/python_firmware/drivers/main.py'):
print "found new main.py file"
os.system("/bin/mv -f /root/python_firmware/drivers/main.py /root/python_firmware/main.py")
#try and delte the file just in case
os.system("/bin/rm -f /root/python_firmware/drivers/main.py")
os.system("/bin/rm -f /root/python_firmware/drivers/main.pyc")
self.sysReboot = True
# TODO Stick non driver file updates here
#modbus dictionary for the ComBox
#multiplier can be multiply or divide or None
#changeType = number or percent
#
self.com1Reads = 0
self.com2Reads = 0
self.com3Reads = 0
self.com4Reads = 0
self.com5Reads = 0
self.com1Errors = 0
self.com2Errors = 0
self.com3Errors = 0
self.com4Errors = 0
self.com5Errors = 0
self.pulses = None
self.modbus_logger = logger.Logger(channel_name="log-modbus",message_sender=self.sendtodb,enabled=True)
self.IOmap = {
"1":"On",
1:"On",
0:"Off",
"0":"Off"
}
#load stored DIO forward rules
#load stored location spoofing data:
try:
with open('/root/python_firmware/drivers/dioForward.p', 'rb') as handle:
self.dioForward = pickle.load(handle)
print "found pickled dictionary"
print self.dioForward
except:
print "couldn't load locSpoof from pickle"
self.dioForward = {
"cloop":{"on":"off","deviceName":"M1","channel":"cloop","unitNum":"1"},
"cloop2":{"on":"off","deviceName":"M1","channel":"cloop2","unitNum":"1"}, # only cloop2 or analog4 will exist
"din1":{"on":"off","deviceName":"M1","channel":"din1","unitNum":"1"}, # on any given m1
"din2":{"on":"off","deviceName":"M1","channel":"din2","unitNum":"1"},
"din3":{"on":"off","deviceName":"M1","channel":"din3","unitNum":"1"},
"din4":{"on":"off","deviceName":"M1","channel":"din4","unitNum":"1"},
"analog1":{"on":"off","deviceName":"M1","channel":"analog1","unitNum":"1"},
"analog2":{"on":"off","deviceName":"M1","channel":"analog2","unitNum":"1"},
"analog3":{"on":"off","deviceName":"M1","channel":"analog3","unitNum":"1"},
"analog4":{"on":"off","deviceName":"M1","channel":"analog4","unitNum":"1"},
"dout1":{"on":"off","deviceName":"M1","channel":"dout1","unitNum":"1"},
"dout2":{"on":"off","deviceName":"M1","channel":"dout2","unitNum":"1"},
"dout3":{"on":"off","deviceName":"M1","channel":"dout3","unitNum":"1"},
"dout4":{"on":"off","deviceName":"M1","channel":"dout4","unitNum":"1"},
"relay1":{"on":"off","deviceName":"M1","channel":"relay1","unitNum":"1"},
"vin":{"on":"off","deviceName":"M1","channel":"vin","unitNum":"1"},
"bat":{"on":"off","deviceName":"M1","channel":"bat","unitNum":"1"},
"temp":{"on":"off","deviceName":"M1","channel":"temp","unitNum":"1"},
"pulse":{"on":"off","deviceName":"M1","channel":"pulse","unitNum":"1"},
"ver":{"on":"off","deviceName":"M1","channel":"ver","unitNum":"1"},
"modcom":{"on":"off","deviceName":"M1","channel":"ver","unitNum":"1"}
}
#load stored analog input data
try:
with open('/root/python_firmware/drivers/analogData.p', 'rb') as handle:
self.analogData = pickle.load(handle)
print "found analogData dictionary"
print self.analogData
except:
print "couldn't load analogData from pickle"
self.analogData = {
"vin":{"units_high":30,
"units_low":0,
"volts_high":30,
"volts_low":0,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0.5,
"min_period":600,
"grp":(3600*6),
"last_value":"",
"last_send_time":0
},
"bat":{"units_high":30,
"units_low":0,
"volts_high":30,
"volts_low":0,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0,
"min_period":3600,
"grp":None,
"last_value":"",
"last_send_time":0
},
"analog1":{"units_high":30,
"units_low":0,
"volts_high":30,
"volts_low":0,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0,
"min_period":30,
"grp":None,
"last_value":"",
"last_send_time":0
},
"analog2":{"units_high":30,
"units_low":0,
"volts_high":30,
"volts_low":0,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0,
"min_period":30,
"grp":None,
"last_value":"",
"last_send_time":0
},
"analog3":{"units_high":30,
"units_low":0,
"volts_high":30,
"volts_low":0,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0,
"min_period":30,
"grp":None,
"last_value":"",
"last_send_time":0
},
"analog4":{"units_high":30,
"units_low":0,
"volts_high":30,
"volts_low":0,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0,
"min_period":30,
"grp":None,
"last_value":"",
"last_send_time":0
},
"cloop":{"units_high":20,
"units_low":3,
"volts_high":20,
"volts_low":3,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0,
"min_period":30,
"grp":None,
"last_value":"",
"last_send_time":0
},
"cloop2":{"units_high":20,
"units_low":3,
"volts_high":20,
"volts_low":3,
"alarm_low":0,
"alarm_high":30,
"action_high":None,
"action_low":None,
"change_amount":0,
"min_period":30,
"grp":None,
"last_value":"",
"last_send_time":0
},
"pulse":{"multiplier":1,
"change_amount":20,
"interval":1800,
"last_value":"",
"last_send_time":0
}
}
#load stored location spoofing data:
try:
with open('/root/python_firmware/drivers/locSpoof.p', 'rb') as handle:
self.locSpoof = pickle.load(handle)
print "found pickled dictionary"
print self.locSpoof
except:
print "couldn't load locSpoof from pickle"
self.locSpoof = { "on":"off","mode":"forward","mac":None}
#load stored value for updating device address on boot
try:
with open('/root/python_firmware/drivers/adrsetonboot.p', 'rb') as handle:
self.adrsetonboot = pickle.load(handle)
print "found adrsetonboot"
print self.adrsetonboot
except:
print "couldn't load adrsetonboot from pickle"
self.adrsetonboot = False
#load stored modbus mappings
try:
with open('/root/python_firmware/drivers/deviceaddress.p', 'rb') as handle:
self.deviceaddress = pickle.load(handle)
print "found pickled dictionary"
print self.deviceaddress
except:
print "couldn't load deviceaddress from pickle"
self.deviceaddress = 1
#load stored modbus mappings
try:
with open('/root/python_firmware/drivers/modbusMap.p', 'rb') as handle:
self.modbusMap = pickle.load(handle)
print "found pickled dictionary"
print self.modbusMap
except:
print "couldn't load modbusMap from pickle"
self.modbusMap = { }
#load stored geo data
try:
with open('/root/python_firmware/drivers/geoData.p', 'rb') as handle:
self.geoData = pickle.load(handle)
print "found pickled Geo Data"
print self.geoData
except:
print "couldn't load modbusMap from pickle"
self.geoData = {}
if self.adrsetonboot or self.adrsetonboot == "True" or self.adrsetonboot == True:
self.changeDeviceAddress(int(self.deviceaddress))
print "updating addresses for modbus"
self.register()
self.finished = threading.Event()
threading.Thread.start(self)
self.last_xbee_sig_time = 0
#this is a required function for all drivers, its goal is to upload some piece of data
#about your device so it can be seen on the web
def register(self):
self.sync = True
self.sendtodb("connected", "true", 0)
#{'c':'none','b':'9600','p':'none','s':'1','f':'Off'}
self.last_signal = 0
self.last_gps = ""
self.last_gps_time = 0
self.last_power = ""
self.last_pulses = -21
self.last_xbee_sig_time = 0
self.syncGeoTags()
with self.lock:
self.syncModbus()
for comport in self.modbusMap:
for address in self.modbusMap[comport]["addresses"]:
for channelName in self.modbusMap[comport]["addresses"][address]:
self.modbusMap[comport]["addresses"][address][channelName]["la"] = ""
self.forwardingMap = {
"1": {
"port":"",
"externalPort":"",
"externalIP":""
},
"2": {
"port":"",
"externalPort":"",
"externalIP":""
},
"3": {
"port":"",
"externalPort":"",
"externalIP":""
},
"4": {
"port":"",
"externalPort":"",
"externalIP":""
}
}
self.last_alarms = ""
self.last_state = ""
self.last_tct1 = ""
self.last_tsp1 = ""
self.last_tmd1 = ""
self.last_tst1 = ""
self.vpnCheckUp()
#self.count = 3001
def stop (self):
self.finished.set()
self.join()
def analogDataSync(self, all=True):
with self.analogLock:
for item in self.analogData:
self.analogData[item]["last_value"] = ""
if all:
for channel in self.analogData[item]:
name = None
if item == "analog1" and channel in analogToChannelMap:
name = "a1-" + analogToChannelMap[channel]
elif item == "analog2" and channel in analogToChannelMap:
name = "a2-" + analogToChannelMap[channel]
elif item == "analog3" and channel in analogToChannelMap:
name = "a3-" + analogToChannelMap[channel]
elif item == "analog4" and channel in analogToChannelMap:
name = "a4-" + analogToChannelMap[channel]
elif item == "cloop" and channel in analogToChannelMap:
name = "cl-" + analogToChannelMap[channel]
elif item == "cloop2" and channel in analogToChannelMap:
name = "cl2-" + analogToChannelMap[channel]
if name is not None:
self.sendtodb(name, str(self.analogData[item][channel]), 0)
#TODO make it chatty
def vpnCheckUp(self):
#get ip address and subnet mask
p = subprocess.Popen("/sbin/uci get network.lan.netmask", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
mask = output.replace("\n","")
self.sendtodb("getmask", mask, 0)
p = subprocess.Popen("/sbin/uci get network.lan.ipaddr", stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
ip = output.replace("\n","")
self.sendtodb("ip", ip, 0)
try:
for i in range(1,5):
for channel in self.vpn.forwardingMap[str(i)]:
if self.vpn.forwardingMap[str(i)][channel] != self.forwardingMap[str(i)][channel]:
print "new value found in the vpn"
if channel == "port":
newchannel = ("port" + str(i))
elif channel == "externalPort":
newchannel = ("eport" + str(i))
elif channel == "externalIP":
newchannel = ("ip" + str(i))
self.sendtodb(str(newchannel), str(self.vpn.forwardingMap[str(i)][channel]), 0)
self.forwardingMap[str(i)][channel] = self.vpn.forwardingMap[str(i)][channel]
self.sendtodb("vpnip", str(self.vpn.get_ip_address("tun0")), 0)
except Exception,e:
print e
def start(self):
# you could add other ddo settings here
thread.start_new_thread(self.loop, ())
# def stop(): uses XBeeSerial.stop()
## Locally defined functions:
def readCountThread(self):
item = "modcom"
#here I will calculate the rate of reads and errors from the modbus/ethernet IP
initValue = self.dioForward[item]["on"] + "," + self.dioForward[item]["deviceName"] + "," + self.dioForward[item]["unitNum"] + "," + self.dioForward[item]["channel"]
self.sendtodb("fwd-modcom", initValue,0)
last_newCom1Errors = -100
last_newCom2Errors = -100
last_newCom3Errors = -100
last_newCom4Errors = -100
last_newCom5Errors = -100
last_newCom1Reads = -100
last_newCom2Reads = -100
last_newCom3Reads = -100
last_newCom4Reads = -100
last_newCom5Reads = -100
lastModCom = ""
while True:
currentCom1Errors = self.com1Errors
currentCom2Errors = self.com2Errors
currentCom3Errors = self.com3Errors
currentCom4Errors = self.com4Errors
currentCom5Errors = self.com5Errors
currentCom1Reads = self.com1Reads
currentCom2Reads = self.com2Reads
currentCom3Reads = self.com3Reads
currentCom4Reads = self.com4Reads
currentCom5Reads = self.com5Reads
time.sleep(60)
newCom1Errors = (self.com1Errors - currentCom1Errors)
newCom2Errors = (self.com2Errors - currentCom2Errors)
newCom3Errors = (self.com3Errors - currentCom3Errors)
newCom4Errors = (self.com4Errors - currentCom4Errors)
newCom5Errors = (self.com5Errors - currentCom5Errors)
newCom1Reads = (self.com1Reads - currentCom1Reads)
newCom2Reads = (self.com2Reads - currentCom2Reads)
newCom3Reads = (self.com3Reads - currentCom3Reads)
newCom4Reads = (self.com4Reads - currentCom4Reads)
newCom5Reads = (self.com5Reads - currentCom5Reads)
self.sendtodb("connected", "true", 0)
if abs(last_newCom1Errors - newCom1Errors) > 1 or (newCom1Errors == 0 and last_newCom1Errors != 0):
self.sendtodb("c1err", str(newCom1Errors), 0)
last_newCom1Errors = newCom1Errors
if abs(last_newCom2Errors - newCom2Errors) > 1 or (newCom2Errors == 0 and last_newCom2Errors != 0):
self.sendtodb("c2err", str(newCom2Errors), 0)
last_newCom2Errors = newCom2Errors
if abs(last_newCom3Errors - newCom3Errors) > 1 or (newCom3Errors == 0 and last_newCom3Errors != 0):
self.sendtodb("c3err", str(newCom3Errors), 0)
last_newCom3Errors = newCom3Errors
if abs(last_newCom4Errors - newCom4Errors) > 1 or (newCom4Errors == 0 and last_newCom4Errors != 0):
self.sendtodb("c4err", str(newCom4Errors), 0)
last_newCom4Errors = newCom4Errors
if abs(last_newCom5Errors - newCom5Errors) > 1 or (newCom5Errors == 0 and last_newCom5Errors != 0):
self.sendtodb("c5err", str(newCom5Errors), 0)
last_newCom5Errors = newCom5Errors
if abs(last_newCom1Reads - newCom1Reads) > 1 or (newCom1Reads == 0 and last_newCom1Reads != 0):
self.sendtodb("c1rd", str(newCom1Reads), 0)
last_newCom1Reads = newCom1Reads
if abs(last_newCom2Reads - newCom2Reads) > 1 or (newCom2Reads == 0 and last_newCom2Reads != 0):
self.sendtodb("c2rd", str(newCom2Reads), 0)
last_newCom2Reads = newCom2Reads
if abs(last_newCom3Reads - newCom3Reads) > 1 or (newCom3Reads == 0 and last_newCom3Reads != 0):
self.sendtodb("c3rd", str(newCom3Reads), 0)
last_newCom3Reads = newCom3Reads
if abs(last_newCom4Reads - newCom4Reads) > 1 or (newCom4Reads == 0 and last_newCom4Reads != 0):
self.sendtodb("c4rd", str(newCom4Reads), 0)
last_newCom4Reads = newCom4Reads
if abs(last_newCom5Reads - newCom5Reads) > 1 or (newCom5Reads == 0 and last_newCom5Reads != 0):
self.sendtodb("c5rd", str(newCom5Reads), 0)
last_newCom5Reads = newCom5Reads
if self.dioForward[item]["on"].lower() == "on":
if int(newCom1Errors) + int(newCom2Errors) + int(newCom3Errors) + int(newCom4Errors) + int(newCom5Errors) > 3:
val = "Off"
else:
val = "On"
if val != lastModCom:
lastModCom = val
ch = self.dioForward[item]["unitNum"]
deviceName = self.dioForward[item]["deviceName"]
chName = self.dioForward[item]["channel"]
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, chName, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, chName, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(item, val, 0)
else:
self.sendtodbDev(ch, chName, val, 0, deviceName)
self.sendtodb(item, val, 0)
def run(self):
#check and see if you need to update all of the modbus device addresses
#example of how to serve modbus rtu data
#serial = self.mcu.rs485
#server = modbus_rtu.RtuServer(serial)
#server.start()
#slave_1 = server.add_slave(1)
#slave_1.add_block('0', 3, 3000, 2)
#slave_1.set_values("0", 100, [25,99])
self.last = {}
#start ftp server
os.system("/usr/sbin/pure-ftpd &")
#start thread for checking GPIO ports
thread.start_new_thread(self.dioThread, ())
#start data counting thread
thread.start_new_thread(self.get_network_bytes, ())
#start thread for rs232 for air quaility guys
#thread.start_new_thread(self.RS232Thread, ())
#on startup send the version number
self.sendtodb("version", str(self.version), 0)
self.sendtodb("log", "system start up", 0)
#reboot the system to install the latest cpu files, this can cause an infinate reboot cycle if we get the cloud version wrong
if self.sysReboot:
#sleep a little just incase we get stuck in a reboot cycle, its always good to wait
print "waiting for restart"
time.sleep(30)
os.system("/root/reboot")
while self.modbusInterfaces == {}:
with self.lock:
for com in self.modbusMap:
port = self.modbusMap[com]["c"]
if port not in self.modbusInterfaces:
if port == "M1-232":
baud = self.modbusMap[com]["b"]
if baud == "":
baud = 9600
else:
baud = int(baud)
#set up rs232 for link to DeapSea
connected = False
#make sure the baud rate gets set
while connected == False:
connected = self.mcu.set232Baud(baud)
time.sleep(1)
serial2 = self.mcu.rs232
self.instrument2 = minimalmodbusM1.Instrument(1, serial2)
self.instrument2.address = 1
self.modbusInterfaces[port] = self.instrument2
print "added M1 232 interface"
elif port == "M1-485":
baud = self.modbusMap[com]["b"]
if baud == "":
baud = 9600
else:
baud = int(baud)
#set up rs232 for link to DeapSea
connected = False
#make sure the baud rate gets set
while connected == False:
connected = self.mcu.set485Baud(baud)
time.sleep(1)
serial4 = self.mcu.rs485
self.instrument1 = minimalmodbusM1.Instrument(1, serial4)
self.instrument1.address = 1
self.modbusInterfaces[port] = self.instrument1
print "added M1 485 interface"
elif port == "M1-MESH":
baud = self.modbusMap[com]["b"]
if baud == "":
baud = 9600
else:
baud = int(baud)
#set up rs232 for link to DeapSea
connected = False
#make sure the baud rate gets set
serialX = self.mcu.xbee
self.instrument1 = minimalmodbusM1.Instrument(1, serialX)
self.instrument1.address = 1
self.modbusInterfaces[port] = self.instrument1
print "added M1 XBEE interface"
elif port == "TCP":
print "adding TCP interface for modbus"
ip = self.modbusMap[com]["b"]
p = self.modbusMap[com]["p"]
self.tcpInstrument = modbus_tcp.TcpMaster(host=ip, port=int(p))
self.modbusInterfaces[port] = self.tcpInstrument
print "done tcp"
print port
print self.modbusInterfaces[port]
elif port == "ETHERNET/IP":
print "adding Ethernet/IP interface for modbus?"
ip = self.modbusMap[com]["b"]
self.ethernetInstrument = ClxDriver()
try:
self.ethernetInstrument.open(ip)
except:
print "Cannot connect to Ethernet/IP (control Logix) device at: ", ip
#p = self.modbusMap[com]["p"]
#Since my ethernet IP lib will timeout crazy fast, I plan on just
#reconnecting with each loop, so I won't try to make my connection string here
self.modbusInterfaces[port] = self.ethernetInstrument
print "done Ethernet/IP"
print port
print self.modbusInterfaces[port]
elif port == "ETHERNET/IP-MICRO":
print "adding Ethernet/IP interface for modbus?"
ip = self.modbusMap[com]["b"]
self.ethernetInstrument = SlcDriver()
try:
self.ethernetInstrument.open(ip)
except:
print "Cannot connect to Ethernet/IP (micrologix) device at: ", ip
#p = self.modbusMap[com]["p"]
#Since my ethernet IP lib will timeout crazy fast, I plan on just
#reconnecting with each loop, so I won't try to make my connection string here
self.modbusInterfaces[port] = self.ethernetInstrument
print "done Ethernet/IP-MIRCO"
print port
print self.modbusInterfaces[port]
else:
connected = False
tries = 0
while not connected:
tries += 1
port = self.modbusMap[com]["c"]
baud = self.modbusMap[com]["b"]
if port == None or port == "none" or port == "None":
connected = True
continue
if baud == "":
baud = 9600
else:
baud = int(baud)
try:
instrument = minimalmodbus.Instrument(port, 1) # port name, slave address (in decimal)
instrument.serial.baudrate = baud
instrument.serial.timeout = 1 # seconds
instrument.address = 1
connected = True
self.modbusInterfaces[port] = instrument
print "added custom interface: " + port
break
except Exception,e:
if tries > 10:
connected = True
break
self.sendtodb("error", str(e), 0)
time.sleep(20)
time.sleep(30)
time.sleep(10)
self.count = 3001
hb_count = 0
thread.start_new_thread(self.readCountThread, ())
while not self.finished.isSet():
self.count += 1
time.sleep(5)
try:
print "################################"
print "#############sending data ######"
try:
self.processModbus()
except Exception,e:
print(str(e))
self.sendtodb("error2", str(e), 0)
except Exception,e: print(str(e))
# We only want the modbus logger to run for one loop, so now that loop is done, catch it here
if self.modbus_logger.is_enabled():
self.modbus_logger.disable()
self.sendtodb("modbusdebug", "Off", 0)
# internal functions & classes
def processModbus(self):
# "mdl": {"length":16, "address":769, "type":"int", "last_val":"", "multiplier":None, "multiplierVal": "1"},
print "checking modbus"
print self.modbusMap
self.modbus_logger.log_message("(!) - Starting modbus loop - (!)")
for com in self.modbusMap:
for address in self.modbusMap[com]["addresses"]:
#get the modbus instrument
instrument = self.modbusInterfaces[self.modbusMap[com]["c"]]
#tcp and ethernet/IP does the device address differently, this only applies to the modbus RTU
if self.modbusMap[com]["c"] != "TCP" and self.modbusMap[com]["c"] != "ETHERNET/IP":
try:
instrument.address = int(address)
except:
continue
ch_un = address
self.modbus_logger.log_message("(!) - Reading device number %s - (!)" % str(address))
for chName in self.modbusMap[com]["addresses"][address]:
with self.lock:
# this while loop is to support modbus retries
modbusRetries = 2
while True:
#time.sleep(1)
#"{'chn':'2-1-v','dn':'M1','da':'1','le':'16','a':'301','f':'3','t':'int','la':null,'m':'none','mv':'1','ct':'number','c':'1','vm':null,'r':'1-200','s':'On'}"
#for a bytearray we will have a new argument called bytearray or bytearraybs for byte swapped.
#"t":"bytearray","bytary":{1:{"chan":"alm1","val0":"Off","val1":"On"},2:{"chan":"alm2","val0":"Off","val1":"On"},3:{},4:{},5:{},6:{},7:{},8:{},9:{},10:{},11:{},12:{},13:{},14:{},15:{}}
try:
status = self.modbusMap[com]["addresses"][address][chName]['s']
#if the status is no on, raise an exception so that is indicated on the modbus log
if status != "On":
modbusRetries = 0 #no point in retrying in this case
raise Exception("register status is not on")
#see if it has the update for a unit number for each register, if not, use the device address
try:
unitNumber = int(str(self.modbusMap[com]["addresses"][address][chName]['un']))
ch = unitNumber
except:
ch = ch_un
if int(ch) < 10:
ch = "0" + str(ch)
deviceName = str(self.modbusMap[com]["addresses"][address][chName]['dn'])
functioncode = str(self.modbusMap[com]["addresses"][address][chName]['f'])
length = int(str(self.modbusMap[com]["addresses"][address][chName]['le']))
regAddress = str(self.modbusMap[com]["addresses"][address][chName]['a'])
type = str(self.modbusMap[com]["addresses"][address][chName]['t'])
last_val = self.modbusMap[com]["addresses"][address][chName]['la']
multiplier = str(self.modbusMap[com]["addresses"][address][chName]['m'])
try:
if multiplier != "function":
multiplierVal = float(self.modbusMap[com]["addresses"][address][chName]['mv'])
else:
multiplierVal = str(self.modbusMap[com]["addresses"][address][chName]['mv'])
except:
multiplierVal = 1
changeType = str(self.modbusMap[com]["addresses"][address][chName]['ct'])
m1Channel = str(self.modbusMap[com]["addresses"][address][chName]['m1ch']) + "-v"
channel = str(self.modbusMap[com]["addresses"][address][chName]['chn'])
try:
vn = self.modbusMap[com]["addresses"][address][chName]['vn']
except:
raise ValueError("Could not read vanity name for register " + regAddress)
vn = None
self.modbus_logger.log_message(" (*) Reading %s on %s " % (vn, regAddress))
try:
min_time = int(self.modbusMap[com]["addresses"][address][chName]['mrt'])
last_time = int(self.modbusMap[com]["addresses"][address][chName]['lrt'])
except:
self.modbusMap[com]["addresses"][address][chName]['mrt'] = 60
self.modbusMap[com]["addresses"][address][chName]['lrt'] = 0
min_time = int(self.modbusMap[com]["addresses"][address][chName]['mrt'])
last_time = int(self.modbusMap[com]["addresses"][address][chName]['lrt'])
#see if there is a period in which you have to get a value, even if it hasn't changed
#sudo code: if (current time - last send time ) > period (and period is not None) send up new point
try:
period = int(self.modbusMap[com]["addresses"][address][chName]['grp'])
if period < 10:
period = None
self.modbus_logger.log_message(" (w) grp set to < 10, will only send on change")
except:
period = None
self.modbus_logger.log_message(" (w) error testing grp, will only send on change")
print "here is your period: ", period
print time.time() - last_time
#check to see if you need to send based on a period that you need a new value
try:
if period != None:
if (time.time() - last_time) > period:
send = True
else:
send = False
else:
send = False
except:
send = False
self.modbus_logger.log_message(" (w) error testing period, will only send on change")
print "here is your send value: ", send
try:
change = int(str(self.modbusMap[com]["addresses"][address][chName]['c']))
except:
change = 0
print "warning: change set to 0"
self.modbus_logger.log_message("warning: change set to 0")
#load the value map
valueMap = self.modbusMap[com]["addresses"][address][chName]['vm']
try:
if len(valueMap.keys()) < 1:
valueMap = None
except:
valueMap = None
range1 = str(self.modbusMap[com]["addresses"][address][chName]['r'])
try:
if len(range1) < 3:
range1 = None
except:
range1 = None
if (range1 == "None" or range1 == "none"):
range1 = None
if multiplier == "None" or multiplier == "none":
multiplier = None
if last_val == None or last_val == "None" or last_val == "none":
last_val = ""
try:
if range1 is not None:
numOfDashes = range1.count('-')
if numOfDashes == 1:
#both positive
high = range1.split("-")[1]
low = range1.split("-")[0]
elif numOfDashes == 2:
#first number is negative
high = range1.split("-")[2]
low = "-" + range1.split("-")[1]
elif numOfDashes == 3:
#both numbers are negative
high = "-" + range1.split("-")[3]
low = "-" + range1.split("-")[1]
except:
range1 = None
self.modbus_logger.log_message(" (w) Error parsing range, range set to none")
#first check for coils:
if type == "coil":
if self.modbusMap[com]["c"] == "TCP":
lst = instrument.execute(int(address), int(functioncode), int(regAddress), 1)
val = lst[0]
else:
val = instrument.read_bit(int(regAddress), functioncode=int(functioncode))
#now check for byte arrary
elif type == "bitarray" or type == "bitarraybs":
print "found bytearray"
arrayOfBits = self.modbusMap[com]["addresses"][address][chName]['bytary']
if type == "bitarraybs":
bs = True
else:
bs = False
#byte arrays are either 16 bit or 32. But mostly 16 will be supported. Thats up to
if self.modbusMap[com]["c"] == "TCP":
lst = instrument.execute(int(address), int(functioncode), int(regAddress), 1)
val = lst[0]
elif self.modbusMap[com]["c"] == "ETHERNET/IP":
val = self.EthernetIPGET(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP read Failed')
elif self.modbusMap[com]["c"] == "ETHERNET/IP-MICRO":
val = self.EthernetIPGETMicro(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP MICRO read Failed')
else:
val = instrument.read_register(int(regAddress), functioncode=int(functioncode))
bits = self.byteArray(val, int(length), bs)
print "here are the bits"
print bits
print arrayOfBits
for number in range(int(length)):
try:
if (last_val[number] != bits[number]) or send == True:
bitInfo = arrayOfBits[number + 1]
if bits[number] == 1 or bits[number] == "1":
val = bitInfo["val1"]
elif bits[number] == 0 or bits[number] == "0":
val = bitInfo["val0"]
if bitInfo["chan"] == "":
modbusRetries = 0 #no point in retrying in this case
raise Exception("bitInfo[\"chan\"] == \"\"") #move on to next register
self.sendtodbDev(ch, bitInfo["chan"], val, 0, deviceName)
except Exception, e:
print "bit error"
print e
bitInfo = arrayOfBits[number + 1]
if bits[number] == 1 or bits[number] == "1":
val = bitInfo["val1"]
elif bits[number] == 0 or bits[number] == "0":
val = bitInfo["val0"]
if bitInfo["chan"] == "":
modbusRetries = 0 #no point in retrying in this case
raise Exception("bitInfo[\"chan\"] == \"\"") #move on to next register
self.sendtodbDev(ch, bitInfo["chan"], val, 0, deviceName)
if (last_val != bits) or send == True:
self.sendtodb(m1Channel, bits, 0)
self.modbusMap[com]["addresses"][address][chName]['la'] = bits
self.modbusMap[com]["addresses"][address][chName]['lrt'] = time.time()
break #break on success
elif int(length) == 16 and (type == "int" or type == "ints"):
if self.modbusMap[com]["c"] == "TCP":
lst = instrument.execute(int(address), int(functioncode), int(regAddress), 1)
val = lst[0]
if type == "ints":
unsigned = val
val = unsigned - 65535 if unsigned > 32767 else unsigned
elif self.modbusMap[com]["c"] == "ETHERNET/IP":
val = self.EthernetIPGET(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP read Failed')
elif self.modbusMap[com]["c"] == "ETHERNET/IP-MICRO":
val = self.EthernetIPGETMicro(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP micro read Failed')
else:
#must be normal read
print "getting int"
try:
val = instrument.read_register(int(regAddress), functioncode=int(functioncode))
print "success reading"
except:
print "error reading modbus value"
raise Exception("error reading modbus value") #raise exception and retry
print val
if type == "ints":
unsigned = val
val = unsigned - 65535 if unsigned > 32767 else unsigned
elif int(length) == 32 and (type == "longbs" or type == "intbs" or type == "intsbs"):
#must be read long or read float
if type == "intbs" or type == "intsbs":
if self.modbusMap[com]["c"] == "TCP":
lst = instrument.execute(int(address), int(functioncode), int(regAddress), 2)
val = int(hex(lst[0]).replace('0x','') + hex(lst[1]).replace('0x',''),16)
if type == "intsbs":
unsigned = val
val = unsigned - 4294967295 if unsigned > 2147483647 else unsigned
elif int(length) == 32 and (type == "long" or type == "int" or type == "ints"):
#must be read long or read float
if type == "int" or type == "ints":
if self.modbusMap[com]["c"] == "TCP":
lst = instrument.execute(int(address), int(functioncode), int(regAddress), 2)
val = int(hex(lst[1]).replace('0x','') + hex(lst[0]).replace('0x',''),16)
if type == "ints":
unsigned = val
val = unsigned - 4294967295 if unsigned > 2147483647 else unsigned
elif self.modbusMap[com]["c"] == "ETHERNET/IP":
val = self.EthernetIPGET(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP read Failed')
elif self.modbusMap[com]["c"] == "ETHERNET/IP-MICRO":
val = self.EthernetIPGETMicro(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP micro read Failed')
else:
val = instrument.read_long(int(regAddress), functioncode=int(functioncode))
if type == "ints":
val = self.int32(int(val))
elif type == "float" and int(length) == 32:
if self.modbusMap[com]["c"] == "TCP":
lst = instrument.execute(int(address), int(functioncode), int(regAddress), 2)
val = round(unpack('f',pack('>HH',lst[0], lst[1],))[0], 3)
elif self.modbusMap[com]["c"] == "ETHERNET/IP":
val = self.EthernetIPGET(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP read Failed')
elif self.modbusMap[com]["c"] == "ETHERNET/IP-MICRO":
val = self.EthernetIPGETMicro(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP micro read Failed')
else:
val = instrument.read_float(int(regAddress), functioncode=int(functioncode))
val = round(val, 3)
print val
elif type == "floatbs" and int(length) == 32:
if self.modbusMap[com]["c"] == "TCP":
lst = instrument.execute(int(address), int(functioncode), int(regAddress), 2)
val = round(unpack('f',pack('>HH',lst[1], lst[0],))[0], 3)
elif self.modbusMap[com]["c"] == "ETHERNET/IP":
val = self.EthernetIPGET(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP read Failed')
elif self.modbusMap[com]["c"] == "ETHERNET/IP-MICRO":
val = self.EthernetIPGETMicro(instrument, com, regAddress)
if val == None:
raise ValueError('Ethernet IP micro read Failed')
else:
t = instrument.read_registers(int(regAddress), 2, functioncode=int(functioncode))
val = round(self.byteSwap32(t), 2)
print val
elif type == "floatbsw" and int(length) == 32:
t = instrument.read_registers(int(regAddress), 2, functioncode=int(functioncode))
val = round(self.byteSwap32(t) ,2)
#now write this to registers to address 0 and 1. Because IWI can't figure out how to use 32 bit floats, we are
#breaking it down into 2 integers. 0 = 16 bit integer left of the decimal place
# 1 = 16 bit integer right of the decimal place
try:
tm = self.modbusInterfaces[self.modbusMap["1"]["c"]]
reg0 = int(str(val).split(".")[0])
reg1 = int(str(val).split(".")[1])
print reg0, reg1
time.sleep(.5)
self.EthernetIPSETMicro(tm, 1, "N7:10", reg0)
#self.instrument2.write_register(0, reg0)
time.sleep(.5)
#self.instrument2.write_register(1, reg1)
self.EthernetIPSETMicro(tm, 1, "N7:11", reg1)
time.sleep(.5)
#self.instrument2.write_register(4, 1)
print "success setting h2s data to plc"
except:
print "failed setting registers for IWI"
raise Exception("failed setting registers for IWI")
print val
else:
modbusRetries = 0 #no point in retrying, unknown type
print "register type does not match any known type"
raise Exception("register type does not match any known type")
#check if there is a multiplier
if multiplier != None:
if multiplier == "divide":
val = round(float((float(val) / float(multiplierVal))), 2)
elif multiplier == "multiply":
val = round(float((float(val) * float(multiplierVal))), 2)
elif multiplier == "function":
x = float(val)
print str(multiplierVal)
try:
val = eval(str(multiplierVal).strip().replace("&", "'"))
print "eval value: "
print val
try:
val = float(val)
except:
type = "str"
except Exception, e:
print e
raise Exception(str(e))
#check and see if we have a range, if its outside the range1 then just ignore the data and continue
if range1 != None and type != "coil" and type != "str":
#validate the value is in the range
try:
if float(val) > float(high) or float(val) < float(low):
print "validation failed, skipping value"
print str(range1)
print str(low) + " - " + str(high)
raise Exception(" (X) Read invalid value, outside of specified range. -" + str(val))
except Exception, e:
print "exception: validation error, skipping value"
raise Exception(" (X) Error testing range, skipping register - " + str(e))
#if we get to this point the read must have worked, so we can count up the succussful read counts
if int(com) == 1:
self.com1Reads +=1
elif int(com) == 2:
self.com2Reads += 1
elif int(com) == 3:
self.com3Reads += 1
elif int(com) == 4:
self.com4Reads += 1
elif int(com) == 5:
self.com5Reads += 1
#check if the data has changed
if changeType == "number":
#compare last value with a change amount to see if we have enough change to send it
#first see if you have an empty string as the last value, if so its the first time and we don't need to compare, but just send the value
if str(last_val) == "" or last_val == None or str(last_val) == "None" or str(last_val) == "none": #may introduce bug if intentionally pass "None" as value
if val != last_val or send == True:
if valueMap != None:
try:
print "found Value map"
print valueMap
updateVal = valueMap[str(int(val))]
print "new Value", val
except:
self.modbus_logger.log_message(" (w) error applying value map")
updateVal = val
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, updateVal, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, updateVal, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, updateVal, 0)
else:
self.sendtodbDev(ch, channel, updateVal, 0, deviceName)
self.sendtodb(m1Channel, updateVal, 0)
else:
self.sendtodb(m1Channel, updateVal, 0)
else:
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodbDev(ch, channel, val, 0, deviceName)
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodb(m1Channel, val, 0)
self.modbusMap[com]["addresses"][address][chName]['la'] = val
self.modbusMap[com]["addresses"][address][chName]['lrt'] = time.time()
break #replaced continue with break to preserve original flow (cause added loop)
elif type == "str":
if (val != last_val and abs(time.time() - last_time) > min_time) or send == True:
if valueMap != None:
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, valueMap[str(val)], 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, valueMap[str(val)], 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, valueMap[str(val)], 0)
else:
self.sendtodbDev(ch, channel, valueMap[str(val)], 0, deviceName)
else:
self.sendtodb(m1Channel, valueMap[str(val)], 0)
else:
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodbDev(ch, channel, val, 0, deviceName)
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodb(m1Channel, val, 0)
self.modbusMap[com]["addresses"][address][chName]['la'] = val
self.modbusMap[com]["addresses"][address][chName]['lrt'] = time.time()
break #replaced continue with break to preserve original flow (cause added loop)
elif type == "coil" :
if (val != last_val and abs(time.time() - last_time) > min_time) or send == True:
if valueMap != None:
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, valueMap[str(val)], 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, valueMap[str(val)], 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, valueMap[str(val)], 0)
else:
self.sendtodbDev(ch, channel, valueMap[str(val)], 0, deviceName)
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodb(m1Channel, valueMap[str(val)], 0)
else:
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodbDev(ch, channel, val, 0, deviceName)
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodb(m1Channel, val, 0)
self.modbusMap[com]["addresses"][address][chName]['la'] = val
self.modbusMap[com]["addresses"][address][chName]['lrt'] = time.time()
break #replaced continue with break to preserve original flow (cause added loop)
elif type == "float" or type == "int" or type == "floatbs" or type == "floatbsw" or type == "ints":
print val
if (abs(float(last_val) - float(val)) > change and abs(time.time() - last_time) > min_time) or send == True:
if valueMap != None:
try:
print "found Value map"
print valueMap
updateVal = valueMap[str(int(val))]
print "new Value", val
except:
updateVal = val
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, updateVal, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, updateVal, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, updateVal, 0)
else:
self.sendtodb(m1Channel, val, 0)
self.sendtodbDev(ch, channel, updateVal, 0, deviceName)
else:
self.sendtodb(m1Channel, updateVal, 0)
else:
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodbDev(ch, channel, val, 0, deviceName)
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodb(m1Channel, val, 0)
self.modbusMap[com]["addresses"][address][chName]['la'] = val
self.modbusMap[com]["addresses"][address][chName]['lrt'] = time.time()
break #this level of indent may be important
#break from the while True loop on success
except Exception,e:
modbusRetries = modbusRetries - 1
if(modbusRetries > 0):
print "had an error on the modbus loop, retrying read"
self.modbus_logger.log_message("Error in modbus loop, retrying")
continue #retry processing the register
else:
print "Error reading register, retries exhausted"
print(str(e))
self.modbus_logger.log_message("(X) Retries Exhausted: " + str(e))
#count up on the error
if int(com) == 1:
self.com1Errors +=1
elif int(com) == 2:
self.com2Errors += 1
elif int(com) == 3:
self.com3Errors += 1
elif int(com) == 4:
self.com4Errors += 1
elif int(com) == 5:
self.com5Errors += 1
break #break from the while true loop on failure
#end while True
def EthernetIPSETMicro(self, instrument, com, regAddress, val):
try:
success = instrument.write_tag(regAddress, val)
except:
self.ethernetInstrument = SlcDriver()
if self.ethernetInstrument.open(self.modbusMap[com]["b"]):
success = self.ethernetInstrument.write_tag(regAddress, val)
else:
return False
return success
def EthernetIPGETMicro(self, instrument, com, regAddress):
try:
val = round(float(instrument.read_tag(regAddress)), 2)
except:
self.ethernetInstrument = SlcDriver()
if self.ethernetInstrument.open(self.modbusMap[com]["b"]):
val = round(float(self.ethernetInstrument.read_tag(regAddress)), 2)
else:
return None
return val
def EthernetIPGET(self, instrument, com, regAddress):
try:
val = instrument.read_tag([regAddress])[0][1]
except:
self.ethernetInstrument = ClxDriver()
if self.ethernetInstrument.open(self.modbusMap[com]["b"]):
val = self.ethernetInstrument.read_tag([regAddress])[0][1]
print val
else:
return None
return val
def EthernetIPSET(self, instrument, com, val):
try:
success = instrument.write_tag(val)
except Exception, e:
print e
self.ethernetInstrument = ClxDriver()
if self.ethernetInstrument.open(self.modbusMap[com]["b"]):
success = self.ethernetInstrument.write_tag(val)
else:
return False
return success
def M1_sync(self, name, value):
self.register()
self.count = 3001
return True
def syncModbus(self):
#{'c':'none','b':'9600','p':'none','s':'1','f':'Off'}
for comport in self.modbusMap:
data = """{"c":"%s", "b":"%s", "p":"%s", "s":"%s", "f":"%s"}""" % (self.modbusMap[comport]["c"],self.modbusMap[comport]["b"],self.modbusMap[comport]["p"],self.modbusMap[comport]["s"],self.modbusMap[comport]["f"] )
name = str(int(comport) * 2) + "s"
self.sendtodbJSON(name, data, 0)
for address in self.modbusMap[comport]["addresses"]:
for channelName in self.modbusMap[comport]["addresses"][address]:
name = self.modbusMap[comport]["addresses"][address][channelName]["m1ch"]
self.sendtodbJSON(name, json.dumps(self.modbusMap[comport]["addresses"][address][channelName]), 0)
try:
vn = self.modbusMap[comport]["addresses"][address][channelName]["vn"]
self.sendtodb(name+"-vn", vn, 0)
hi = self.modbusMap[comport]["addresses"][address][channelName]["ah"]
self.sendtodb(name+"-hi", hi, 0)
low = self.modbusMap[comport]["addresses"][address][channelName]["al"]
self.sendtodb(name+"-low", low, 0)
# TODO make it chatty
except Exception, e:
print "error finding vanity name"
print e
def handleModbusEntry(self, name, value):
#odd naming convention needs to be kept up with
#check if there is an integer in on the left side of "-" for validation
try:
test = int(name.split("-")[0])
com = str(test/2)
except:
return False
newVal = value.replace("'", '"')
newJson = json.loads(newVal)
#{'s': 'Off'}
#check here to see if this is a deletion
if "s" in newJson and not "a" in newJson and newJson["s"] == "Off":
print "we have a delete request for the channel: " + name
try:
for comport in self.modbusMap:
for address in self.modbusMap[comport]["addresses"]:
for channelName in self.modbusMap[comport]["addresses"][address]:
if self.modbusMap[comport]["addresses"][address][channelName]["m1ch"] == name:
del self.modbusMap[comport]["addresses"][address][channelName]
#now see if there are any other channels at this address, if not delete the address also
if len(self.modbusMap[comport]["addresses"][address]) < 1:
del self.modbusMap[comport]["addresses"][address]
self.sendtodb(name, "", 0)
return True
except:
self.sendtodb(name, "", 0)
return True
#we need to see if this is changing from one address to another, if so delete the old one
#if there usage of this channel, delete it, actually just always deleting it could work,
#then if there isn't any other regersters at that address, delete that entire address
try:
for comport in self.modbusMap:
for address in self.modbusMap[comport]["addresses"]:
for channelName in self.modbusMap[comport]["addresses"][address]:
if self.modbusMap[comport]["addresses"][address][channelName]["m1ch"] == name:
del self.modbusMap[comport]["addresses"][address][channelName]
#now see if there are any other channels at this address, if not delete the address also
if len(self.modbusMap[comport]["addresses"][address]) < 1:
del self.modbusMap[comport]["addresses"][address]
#self.sendtodb(name, "", 0)
except Exception, e:
try:
for comport in self.modbusMap:
for address in self.modbusMap[comport]["addresses"]:
for channelName in self.modbusMap[comport]["addresses"][address]:
if self.modbusMap[comport]["addresses"][address][channelName]["m1ch"] == name:
del self.modbusMap[comport]["addresses"][address][channelName]
#now see if there are any other channels at this address, if not delete the address also
if len(self.modbusMap[comport]["addresses"][address]) < 1:
del self.modbusMap[comport]["addresses"][address]
#self.sendtodb(name, "", 0)
except Exception, e:
print "deletion error"
print e
channelName = name
devAddress = newJson["da"]
newJson["m1ch"] = name
newEntry = {channelName : newJson}
#first check and see if the address already exists
if devAddress in self.modbusMap[com]["addresses"]:
#if it is here, then just add a new item to the dictionary
self.modbusMap[com]["addresses"][devAddress][channelName] = newJson
pass
else:
#make a new address entry for this com port
self.modbusMap[com]["addresses"][devAddress] = newEntry
self.sendtodbJSON(name, json.dumps(newJson), 0)
return True
def handleComSetup(self, name, value):
interfaces = ["2s","4s","6s","8s","10s","12s","14s","16s","18s","20s"]
if name in interfaces:
try:
com = str(int(name.replace("s","")) / 2)
except Exception,e:
print "error with modbus handleComSetup"
print e
return False
#this is the com settings for 232
#looks like this:{'c':'M1-232','b':'9600','p':'none','s':'1','f':'Off'}
#c = com port, b = baud, p = parity, s = stop bit, f = flow control
print value
#{'c':'none','b':'9600','p':'none','s':'1','f':'Off'}
newVal = value.replace("'", '"')
newJson = json.loads(newVal)
print newJson
port = newJson["c"]
baud = newJson["b"]
parity = newJson["p"]
stopbit = newJson["s"]
flow = newJson["f"]
print "I'm at location 12"
#update the interface:
connected = False
tries = 0
#first check and see if the com port has been set up before
if com in self.modbusMap:
print "this com port is already here"
#if the comport is already here, just change its settings and be on your way!
self.modbusMap[com]["c"] = port
self.modbusMap[com]["b"] = baud
self.modbusMap[com]["p"] = parity
self.modbusMap[com]["s"] = stopbit
self.modbusMap[com]["f"] = flow
else:
#if its new we need to add it, but we need to make sure this is done before we try and add devices to it.
self.modbusMap[com] = {
"c": port,
"b": baud,
"p":parity,
"s":stopbit,
"f":flow,
"addresses": {}
}
if port == "M1-232":
baud = self.modbusMap[com]["b"]
if baud == "":
baud = 9600
else:
baud = int(baud)
#set up rs232 for link to DeapSea
connected = False
#make sure the baud rate gets set
while connected == False:
connected = self.mcu.set232Baud(baud)
time.sleep(1)
serial2 = self.mcu.rs232
self.instrument2 = minimalmodbusM1.Instrument(1, serial2)
self.instrument2.address = 1
self.modbusInterfaces[port] = self.instrument2
print "added M1 232 interface"
elif port == "M1-485":
baud = self.modbusMap[com]["b"]
if baud == "":
baud = 9600
else:
baud = int(baud)
#set up rs232 for link to DeapSea
connected = False
#make sure the baud rate gets set
while connected == False:
connected = self.mcu.set485Baud(baud)
time.sleep(1)
serial4 = self.mcu.rs485
self.instrument1 = minimalmodbusM1.Instrument(1, serial4)
self.instrument1.address = 1
self.modbusInterfaces[port] = self.instrument1
print "added M1 485 interface"
elif port == "M1-MESH":
baud = self.modbusMap[com]["b"]
if baud == "":
baud = 9600
else:
baud = int(baud)
#set up rs232 for link to DeapSea
connected = False
#make sure the baud rate gets set
serialX = self.mcu.xbee
self.instrument1 = minimalmodbusM1.Instrument(1, serialX)
self.instrument1.address = 1
self.modbusInterfaces[port] = self.instrument1
print "added M1 XBEE interface"
elif port == "TCP":
ip = self.modbusMap[com]["b"]
p = self.modbusMap[com]["p"]
self.tcpInstrument = modbus_tcp.TcpMaster(host=ip, port=int(p))
self.modbusInterfaces[port] = self.tcpInstrument
elif port == "ETHERNET/IP":
print "adding Ethernet/IP interface for modbus?"
ip = self.modbusMap[com]["b"]
#p = self.modbusMap[com]["p"]
#Since my ethernet IP lib will timeout crazy fast, I plan on just
#reconnecting with each loop, so I won't try to make my connection string here
self.modbusInterfaces[port] = ip
print "done Ethernet/IP"
elif port == "ETHERNET/IP-MICRO":
print "adding Ethernet/IP interface for modbus?"
ip = self.modbusMap[com]["b"]
self.ethernetInstrument = SlcDriver()
self.ethernetInstrument.open(ip)
#p = self.modbusMap[com]["p"]
#Since my ethernet IP lib will timeout crazy fast, I plan on just
#reconnecting with each loop, so I won't try to make my connection string here
self.modbusInterfaces[port] = self.ethernetInstrument
print "done Ethernet/IP-MIRCO"
print port
print self.modbusInterfaces[port]
else:
connected = False
tries = 0
while not connected:
tries += 1
port = self.modbusMap[com]["c"]
baud = self.modbusMap[com]["b"]
if port == None or port == "none" or port == "None":
connected = True
continue
if baud == "":
baud = 9600
else:
baud = int(baud)
try:
instrument = minimalmodbus.Instrument(port, 1) # port name, slave address (in decimal)
instrument.serial.baudrate = baud
instrument.serial.timeout = 1 # seconds
instrument.address = 1
connected = True
self.modbusInterfaces[port] = instrument
print "added custom interface: " + port
break
except Exception,e:
if tries > 10:
connected = True
break
self.sendtodb("error", str(e), 0)
print "new com port setup"
print "I'm at location 14"
print self.modbusMap
self.sendtodbJSON(name, json.dumps(newJson), 0)
"""self.modbusMap = { "M1-485": {
"port": "/dev/ttySP4",
"baud": "",
"parity":"",
"stopbits":"",
"flowcontrol":"",
"addresses": {
"1": {"p4": {"reg":"299","length":32, "address":1, "functioncode":3, "type":"int", "last_val":"", "multiplier":None, "multiplierVal": 1, "changeType":"number", "change":0, "valueMap":None, "range":None}}
}
}
}
"""
def dioThread(self):
#get modem id on boot
try:
mdn = self.mcu.get_modem_id()
if mdn is not None:
self.sendtodb("mdn", mdn, 0)
else:
mdn = self.mcu.get_modem_id()
if mdn is not None:
self.sendtodb("mdn", mdn, 0)
time.sleep(1)
#sim = self.mcu.get_sim_id()
#if sim is not None:
# self.sendtodb("sim", sim, 0)
#else:
# sim = self.mcu.get_sim_id()
# if sim is not None:
# self.sendtodb("sim", sim, 0)
except:
pass
#items to check for change:
changeDict = {
"analog1":2,
"analog2":2,
"analog3":2,
"analog4":2,
"vin":10,
"bat":1,
"temp":3,
"cloop":0.1
}
while True:
try:
with self.analogLock:
self.currentDict = self.mcu.getDict()
if self.last_power != "":
#check the power state:
if float(self.currentDict["vin"]) > 7 and self.last_power == False:
print "power coming on, send True"
self.last_power = True
self.sendtodb("power", "on", 0)
elif float(self.currentDict["vin"]) < 7 and self.last_power == True:
self.last_power = False
self.sendtodb("power", "off", 0)
else:
#check the initial state of the power
if float(self.currentDict["vin"]) > 7:
print "power coming on, send True"
self.last_power = True
self.sendtodb("power", "on", 0)
else:
self.last_power = False
self.sendtodb("power", "off", 0)
for item in self.currentDict:
try:
if self.sync == False:
#"analog2":{"units_high":30,
#"units_low":0,
#"volts_high":30,
#"volts_low":0,
#"alarm_low":0,
#"alarm_high":30,
#"action_high":None,
#"action_low":None,
#"change_amount":0,
#"min_period":30,
#"grp":None,
#"last_value":"",
#"last_send_time":0
#},
# ((high units - low units) / (high volts - low volts) * (current reading - low volts)) + low units
if item == "pulse":
if "pulse" not in self.analogData:
self.analogData[item] = {"multiplier":1,
"change_amount":20,
"interval":1800,
"last_value":"",
"last_send_time":0
}
#last_val = self.analogData[item]["last_value"]
change = float(self.analogData[item]["change_amount"])
last_time = float(self.analogData[item]["last_send_time"])
interval = int(self.analogData[item]["interval"])
multiplier = float(self.analogData[item]["multiplier"])
#on trigger event send total pulses, and pulses per hour with units
#things to track: interval to check pulses, change amount, multiplier
if abs(int(self.last_pulses) - int(self.currentDict[item])) > int(change) or time.time() - int(last_time) > interval:
self.analogData[item]["last_send_time"] = time.time()
#send up rate per hour
perHour = ( 60 / ((time.time() - int(last_time))/60)) * abs(int(self.last_pulses) - int(self.currentDict[item]))
self.sendtodb("pph", str(round(perHour * multiplier, 2)), 0)
self.sendtodb("ppm", str(round((perHour/60) * multiplier, 2)), 0)
self.process_pulses(int(self.currentDict[item]), multiplier)
self.last_pulses = int(self.currentDict[item])
continue
if item in self.analogData:
#get its value, its last value, its required change amount, and its last time it sent
val = float(self.currentDict[item])
units_high = float(self.analogData[item]["units_high"])
units_low = float(self.analogData[item]["units_low"])
volts_high = float(self.analogData[item]["volts_high"])
volts_low = float(self.analogData[item]["volts_low"])
val = round(((units_high - units_low) / (volts_high - volts_low) * (val - volts_low)) + units_low, 2)
last_val = self.analogData[item]["last_value"]
change = float(self.analogData[item]["change_amount"])
last_time = float(self.analogData[item]["last_send_time"])
min_time = float(self.analogData[item]["min_period"])
gauranteed_report_period = self.analogData[item]["grp"]
send = False
if gauranteed_report_period != None:
if gauranteed_report_period < 5:
gauranteed_report_period = None
if last_val == "":
last_val = 0
send = True
elif gauranteed_report_period != None:
#if the gauranteed period is met, send = True. Or if its the first run (we know its the first run by the last_val = ""
if time.time() - last_time > gauranteed_report_period:
send = True
else:
send = False
#check to see if you have reached a meaningful change amount and time or a guaranteed report period
if (abs(float(last_val) - float(val)) > change and abs(time.time() - last_time) > min_time) or send == True:
self.analogData[item]["last_value"] = val
self.analogData[item]["last_send_time"] = time.time()
val = str(val)
if self.dioForward[item]["on"].lower() == "on":
ch = self.dioForward[item]["unitNum"]
deviceName = self.dioForward[item]["deviceName"]
chName = self.dioForward[item]["channel"]
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, chName, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, chName, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(item, val, 0)
else:
self.sendtodbDev(ch, chName, val, 0, deviceName)
self.sendtodb(item, val, 0)
else:
self.sendtodb(item, val, 0)
#for binary data, check if its changed, that should always be enough, maybe we can get a guarateed report period later for I/O's
elif self.currentDict[item] != self.last[item]:
if item in changeDict:
if abs(float(self.currentDict[item]) - float(self.last[item])) > changeDict[item]:
if self.dioForward[item]["on"].lower() == "on":
ch = self.dioForward[item]["unitNum"]
deviceName = self.dioForward[item]["deviceName"]
chName = self.dioForward[item]["channel"]
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, chName, self.currentDict[item], 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, chName, self.currentDict[item], 0, deviceName, self.locSpoof["mac"])
self.sendtodb(item, self.currentDict[item], 0)
else:
self.sendtodbDev(ch, chName, self.currentDict[item], 0, deviceName)
self.sendtodb(item, self.currentDict[item], 0)
else:
self.sendtodb(item, self.currentDict[item], 0)
else:
try:
print "new value for: " + item
if self.dioForward[item]["on"].lower() == "on":
ch = self.dioForward[item]["unitNum"]
deviceName = self.dioForward[item]["deviceName"]
chName = self.dioForward[item]["channel"]
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, chName, self.currentDict[item], 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, chName, self.currentDict[item], 0, deviceName, self.locSpoof["mac"])
self.sendtodb(item, self.currentDict[item], 0)
else:
self.sendtodbDev(ch, chName, self.currentDict[item], 0, deviceName)
self.sendtodb(item, self.currentDict[item], 0)
else:
self.sendtodb(item, self.currentDict[item], 0)
except:
pass
else:
try:
if item == "pulse":
continue
if item in self.analogData:
val = float(self.currentDict[item])
units_high = float(self.analogData[item]["units_high"])
units_low = float(self.analogData[item]["units_low"])
volts_high = float(self.analogData[item]["volts_high"])
volts_low = float(self.analogData[item]["volts_low"])
val = round(((units_high - units_low) / (volts_high - volts_low) * (val - volts_low)) + units_low, 2)
self.analogData[item]["last_value"] = val
self.analogData[item]["last_send_time"] = time.time()
self.currentDict[item] = str(val)
if self.dioForward[item]["on"].lower() == "on":
ch = self.dioForward[item]["unitNum"]
deviceName = self.dioForward[item]["deviceName"]
chName = self.dioForward[item]["channel"]
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, chName, self.currentDict[item], 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, chName, self.currentDict[item], 0, deviceName, self.locSpoof["mac"])
self.sendtodb(item, self.currentDict[item], 0)
else:
self.sendtodbDev(ch, chName, self.currentDict[item], 0, deviceName)
else:
self.sendtodb(item, self.currentDict[item], 0)
except:
pass
except Exception, e:
print e
if self.sync == True:
self.sync = False
self.last.update(self.currentDict)
time.sleep(.5)
#check geo fences and signal strength
gps = self.mcu.gps
try:
lat1 = self.last_gps.split(",")[0]
long1 = self.last_gps.split(",")[1]
lat2 = gps.split(",")[0]
long2 = gps.split(",")[1]
distance_traveled = self.mcu.distanceBetween(long1, lat1, long2, lat2)
except:
distance_traveled = 0
if (gps != self.last_gps and abs(time.time() - self.last_gps_time) > 43200) or distance_traveled > 0.0625:
if gps != "0.0,-0.0":
self.last_gps = gps
self.last_gps_time = time.time()
self.sendtodb("gps", gps, 0)
try:
try:
if self.mcu.FLY == True:
if (time.time() - self.last_xbee_sig_time) > 3600:
self.sendtodb("signal", "0", 0)
self.last_xbee_sig_time = time.time()
except:
print "not a fly"
else:
signal = self.mcu.signal
if signal is not None:
if int(signal) != int(self.last_signal):
self.sendtodb("signal", str(signal), 0)
self.last_signal = int(signal)
else:
print "signal returned None"
except Exception,e:
print "error with signal"
print e
signal = self.mcu.signal
if signal is not None:
if int(self.last_signal) != int(signal):
self.sendtodb("signal", str(signal), 0)
self.last_signal = int(signal)
#UNCOMMENT AND IMPLEMENT PUSH CONTROL WHEN YOU HAVE MORE THAN 3 seconds
#send 3g vs 4g connection status to UI
#try:
# connType = self.mcu.connType
# if connType == 2:
# self.sendtodb("connType", "3g", 0)
# elif connType == 6:
# self.sendtodb("connType", "3g", 0)
# elif connType == 7:
# self.sendtodb("connType", "4g LTE", 0)
# else:
# self.sendtodb("connType", "Error", 0)
#except Exception, e:
# print "error sending 3g vs 4g connection type to db"
# print e
if len(gps) > 6:
for geoTag in self.geoData:
lat1 = self.geoData[geoTag]["lat"]
long1 = self.geoData[geoTag]["long"]
lat2 = gps.split(",")[0]
long2 = gps.split(",")[1]
distance = self.mcu.distanceBetween(long1, lat1, long2, lat2)
if distance > float(self.geoData[geoTag]["distance"]):
if self.geoData[geoTag]["alarm"] != "out":
self.geoData[geoTag]["alarm"] = "out"
self.sendtodb("geo_a1", "out", 0)
else:
if self.geoData[geoTag]["alarm"] != "in":
self.geoData[geoTag]["alarm"] = "in"
self.sendtodb("geo_a1", "in", 0)
except Exception, e:
print "in M1"
print e
def changeDeviceAddress(self, new):
with self.lock:
try:
for com in self.modbusMap:
for address in self.modbusMap[com]["addresses"]:
if int(new) != int(address):
#this is one we need to repace
#1. update all of the device address fields
#2. copy the object and replace it back with the correct device address in the main object
for chName in self.modbusMap[com]["addresses"][address]:
self.modbusMap[com]["addresses"][address][chName]['da'] = str(new)
newObj = copy.deepcopy(self.modbusMap[com]["addresses"][address])
#attach the copy at the new address
self.modbusMap[com]["addresses"][str(new)] = newObj
#delete the old object
del self.modbusMap[com]["addresses"][address]
#update persistant dictionary
with open('/root/python_firmware/drivers/modbusMap.p', 'wb') as handle:
pickle.dump(self.modbusMap, handle)
except Exception, e:
print "error changing address"
print e
return "Error Changing Address"
return True
def genericSet(self, name, value, id, longId=None):
if name.startswith("fwd-"):
self.updateDIOForward(name, value)
return True
if "adrsetonboot" in name:
#save this to a file
if value == "On" or value == "on" or value == 1 or value == "1" or value == "true" or value == "True":
val = True
else:
val = False
#update persistant value
with open('/root/python_firmware/drivers/adrsetonboot.p', 'wb') as handle:
pickle.dump(val, handle)
self.sendtodb(name, value, 0)
return True
if "deviceaddress" in name:
print "found new device address"
success = self.changeDeviceAddress(int(value))
#hardcoded for flowco, need to adjust main.py to include more detials about which device this is
self.sendtodbDev("01", "deviceaddress", value, 0, "poc")
self.sendtodb("deviceaddress", value, 0)
#update persistant value
with open('/root/python_firmware/drivers/deviceaddress.p', 'wb') as handle:
pickle.dump(int(value), handle)
return success
# Trigger for turning on modbus debugger. It is turned off after one modbus loop
if "modbusdebug" in name:
if value == "On" or value == "on" or value == 1 or value == "1" or value == "true" or value == "True":
val = "On"
self.modbus_logger.enable()
else:
val = "Off"
self.modbus_logger.disable()
self.sendtodb("modbusdebug",str(val),0)
return True
if "reset-pulse" in name:
if value == "1" or value == 1 or value == True or value == "True" or value == "true":
self.pulses["reset-flag"] = 1
self.sendtodb("reset-pulse", str(self.pulses["reset-flag"]), 0)
else:
self.pulses["reset-flag"] = 0
self.sendtodb("reset-pulse", str(self.pulses["reset-flag"]), 0)
#update persistant dictionary
with open('/root/python_firmware/drivers/pulses.p', 'wb') as handle:
pickle.dump(self.pulses, handle)
return True
if "modbuswrite" in name or name == "modbuswrite" or "plcwrite" in name or name == "plcwrite":
try:
#[{"com":"1","device_address":"1","register_address":"0","values":[1]},{"com":"1","device_address":"1","register_address":"299","type":"32/16/coil","values":[256]}]
# [{'com':'1','device_address":'1','register_address':'0','values':[1]}]
newVal = value.replace("'", '"')
newJson = json.loads(newVal)
for set in newJson:
com = set["com"]
try:
regAddress = set["register_address"]
device = int(set["device_address"])
except:
pass
try:
type = str(set["type"])
except:
type = False
values = set["values"]
with self.lock:
instrument = self.modbusInterfaces[self.modbusMap[com]["c"]]
if self.modbusMap[com]["c"] == "TCP":
instrument.execute(device, cst.WRITE_MULTIPLE_REGISTERS, int(regAddress), output_value=values)
elif self.modbusMap[com]["c"] == "ETHERNET/IP":
self.ethernetInstrument = ClxDriver()
self.ethernetInstrument.open(self.modbusMap[com]["b"])
instrument = self.ethernetInstrument
newLst = []
for i in values:
typeOfData = instrument.read_tag([str(i[0])])[0][2]
if 'INT' in typeOfData or 'BOOL' in typeOfData:
newValue = int(str(i[1]))
#elif str(i[2]) == 'BOOL':
# newValue = boot(int(i[1]))
else:
newValue = float(str(i[1]))
newLst.append((str(i[0]),newValue,str( typeOfData ) ))
print "new List"
print newLst
self.EthernetIPSET(instrument, com, newLst)
elif len(values) == 1 and type == "16":
values = values[0]
instrument.write_register(int(regAddress), values, functioncode=6)
time.sleep(1)
newVal = instrument.read_register(int(regAddress))
thread.start_new_thread( self.modbusWriteCheckup, ( int(regAddress), newVal))
elif len(values) == 1 and type == "32":
values = float(values[0])
instrument.write_float(int(regAddress), values)
time.sleep(1)
newVal = instrument.read_float(int(regAddress))
thread.start_new_thread( self.modbusWriteCheckup, ( int(regAddress), newVal))
elif len(values) == 1 and type == "coil":
values = values[0]
instrument.write_bit(int(regAddress), int(values), functioncode=5)
time.sleep(1)
newVal = instrument.read_bit(int(regAddress), functioncode=int(1))
thread.start_new_thread( self.modbusWriteCheckup, ( int(regAddress), newVal))
elif len(values) == 1 and type == "long":
values = values[0]
instrument.write_long(int(regAddress), int(values))
time.sleep(1)
newVal = instrument.read_long(int(regAddress))
thread.start_new_thread( self.modbusWriteCheckup, ( int(regAddress), newVal))
else:
instrument.write_registers(int(regAddress), values)
return True
except Exception, e:
print "modbus write error"
print e
if "The slave is indicating an error" in e:
e = "The slave is indicating an error, can't write regerister"
return str(e)
print "I'm at location 1"
try:
interfaces = ["2s","4s","6s","8s","10s","12s","14s","16s","18s","20s"]
if name in interfaces:
with self.lock:
print "I'm at location 2"
self.handleComSetup(name, value)
#update persistant dictionary
with open('/root/python_firmware/drivers/modbusMap.p', 'wb') as handle:
pickle.dump(self.modbusMap, handle)
return True
try:
print "I'm at location 3"
if name.split("-")[2] == 'v':
#this is a channel set, for future use
pass
except:
pass
#2-1","value":"{'chn':'2-1-v','dn':'M1','le':'16','a':'301','f':'3','t':'int','la':null,'m':'none','mv':'1','ct':'number','c':'1','vm':null,'r':'1-200','s':'On'}"
interfaces = ["2","4","6","8","10","12","14","16","18","20"]
if name.split("-")[0] in interfaces:
with self.lock:
success = self.handleModbusEntry(name, value)
#update persistant dictionary
with open('/root/python_firmware/drivers/modbusMap.p', 'wb') as handle:
pickle.dump(self.modbusMap, handle)
if success:
return True
else:
return False
except Exception,e:
print(str(e))
return False
if name.split("-")[0] == "a1" or name.split("-")[0] == "a2" or name.split("-")[0] == "a3" or name.split("-")[0] == "a4" or name.split("-")[0] == "cl" or name.split("-")[0] == "cl2" or name.split("-")[0] == "pls":
try:
value = float(value)
except:
return(" Value must be a float or integer")
return self.processAnalog(name, value)
#analog inputs (a1-4 and cloop) need 4 data points each set for calibration
#Volts Low that ties to Units Low
#Volts hight that ties to Units High
#if Volts are lower than low, ignore (set to lowest unit value). If Volts are higher than high, ignor (set to highest units value)
#formula for displaying value: ((high units - low units) / (high volts - low volts) * (current reading - low volts)) + low units
#high / low alarm matrix for digitl outputs and relay
#sets from M1 to M1 with I/O mapping, probably dont need
def modbusWriteCheckup(self, registerAddress, val):
time.sleep(6)
print "staring process of modbus ping back"
print val, registerAddress
for com in self.modbusMap:
for address in self.modbusMap[com]["addresses"]:
ch_un = address
for chName in self.modbusMap[com]["addresses"][address]:
#time.sleep(1)
regAddress = str(self.modbusMap[com]["addresses"][address][chName]['a'])
print regAddress, registerAddress
if int(registerAddress) == int(regAddress):
print "we found our match for quick update of modbus write"
#see if it has the update for a unit number for each register, if not, use the device address
try:
unitNumber = int(str(self.modbusMap[com]["addresses"][address][chName]['un']))
ch = unitNumber
except:
ch = ch_un
if int(ch) < 10:
ch = "0" + str(ch)
deviceName = str(self.modbusMap[com]["addresses"][address][chName]['dn'])
functioncode = str(self.modbusMap[com]["addresses"][address][chName]['f'])
length = int(str(self.modbusMap[com]["addresses"][address][chName]['le']))
regAddress = str(self.modbusMap[com]["addresses"][address][chName]['a'])
type = str(self.modbusMap[com]["addresses"][address][chName]['t'])
last_val = self.modbusMap[com]["addresses"][address][chName]['la']
multiplier = str(self.modbusMap[com]["addresses"][address][chName]['m'])
try:
if multiplier != "function":
multiplierVal = float(self.modbusMap[com]["addresses"][address][chName]['mv'])
else:
multiplierVal = str(self.modbusMap[com]["addresses"][address][chName]['mv'])
except:
multiplierVal = 1
changeType = str(self.modbusMap[com]["addresses"][address][chName]['ct'])
m1Channel = str(self.modbusMap[com]["addresses"][address][chName]['m1ch']) + "-v"
channel = str(self.modbusMap[com]["addresses"][address][chName]['chn'])
try:
min_time = int(self.modbusMap[com]["addresses"][address][chName]['mrt'])
last_time = int(self.modbusMap[com]["addresses"][address][chName]['lrt'])
except:
self.modbusMap[com]["addresses"][address][chName]['mrt'] = 60
self.modbusMap[com]["addresses"][address][chName]['lrt'] = 0
min_time = int(self.modbusMap[com]["addresses"][address][chName]['mrt'])
last_time = int(self.modbusMap[com]["addresses"][address][chName]['lrt'])
#see if there is a period in which you have to get a value, even if it hasn't changed
#sudo code: if (current time - last send time ) > period (and period is not None) send up new point
try:
period = int(self.modbusMap[com]["addresses"][address][chName]['grp'])
if period < 10:
period = None
except:
period = None
print "here is your period: ", period
print time.time() - last_time
#load the value map
valueMap = self.modbusMap[com]["addresses"][address][chName]['vm']
try:
if len(valueMap.keys()) < 1:
valueMap = None
except:
valueMap = None
#check if there is a multiplier
if multiplier != None:
if multiplier == "divide":
val = round(float((float(val) / float(multiplierVal))), 2)
elif multiplier == "multiply":
val = round(float((float(val) * float(multiplierVal))), 2)
elif multiplier == "function":
x = float(val)
print str(multiplierVal)
try:
val = eval(multiplierVal.replace("&", "'"))
print "eval value: "
print val
try:
val = float(val)
except:
type = "str"
except Exception, e:
print e
if valueMap != None:
try:
print "found Value map"
print valueMap
updateVal = valueMap[str(int(val))]
print "new Value", val
except:
updateVal = val
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, updateVal, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, updateVal, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, updateVal, 0)
else:
self.sendtodbDev(ch, channel, updateVal, 0, deviceName)
self.sendtodb(m1Channel, updateVal, 0)
else:
self.sendtodb(m1Channel, updateVal, 0)
else:
if deviceName != "M1":
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, channel, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodbDev(ch, channel, val, 0, deviceName)
self.sendtodb(m1Channel, val, 0)
else:
self.sendtodb(m1Channel, val, 0)
self.modbusMap[com]["addresses"][address][chName]['la'] = val
self.modbusMap[com]["addresses"][address][chName]['lrt'] = time.time()
def processAnalog(self, name, value):
with self.analogLock:
try:
if name.split("-")[0] == "a1":
analogName = "analog1"
elif name.split("-")[0] == "a2":
analogName = "analog2"
elif name.split("-")[0] == "a3":
analogName = "analog3"
elif name.split("-")[0] == "a4":
analogName = "analog4"
elif name.split("-")[0] == "cl":
analogName = "cloop"
elif name.split("-")[0] == "cl2":
analogName = "cloop2"
elif name.split("-")[0] == "pls":
analogName = "pulse"
chName = analogMap[name.split("-")[1]]
self.analogData[analogName][chName] = float(value)
#update persistant dictionary
with open('/root/python_firmware/drivers/analogData.p', 'wb') as handle:
pickle.dump(self.analogData, handle)
self.sendtodb(name, value, 0)
except Exception, e:
return str(e)
return True
pass
def M1_vpnpf(self, name, value):
#value = "1,8080,192.168.1.2,80"
v = value.split(",")
if v[1] == "del":
self.vpn.delForward(1)
return True
else:
number = v[0]
port = v[1]
ip = v[2]
exPort = v[3]
self.vpn.addForward(number, port, exPort, ip)
self.vpnCheckUp()
self.sendtodb("vpnpf", value, 0)
return True
def M1_vpn(self, name, value):
try:
#on,lewis@lewis.com,password,subnet,ip,domain
values = value.split(",")
if values[0] == "On" or values[0] == "on" or values[0] == 1 or values[0] == "1":
self.vpn.turnOn("http://54.221.213.207:5000", values[1], values[2], self.mac, values[3], values[4], values[5])
elif values[0] == "Off" or values[0] == "off" or values[0] == 0 or values[0] == "0":
self.vpn.turnOff()
time.sleep(30)
self.vpnCheckUp()
#remove the password from the list
newValues = values[0] + "," + values[1] + "," + " " + "," + values[3] + "," + values[4]
self.sendtodb("vpn", newValues, 0)
except Exception,e:
print(str(e))
self.sendtodb("error", (str(e) + " most likely wrong username and password"), 0)
return str(e)
return True
def M1_dout1(self, name, value):
success = self.mcu.digitalOut1(str(value))
if success:
self.sendtodb(name, str(value), 0)
#return True/False
return success
def M1_dout2(self, name, value):
success = self.mcu.digitalOut2(str(value))
if success:
self.sendtodb(name, str(value), 0)
#return True/False
return success
def M1_dout3(self, name, value):
success = self.mcu.digitalOut3(str(value))
if success:
self.sendtodb(name, str(value), 0)
#return True/False
return success
def M1_dout4(self, name, value):
success = self.mcu.digitalOut4(str(value))
if success:
self.sendtodb(name, str(value), 0)
#return True/False
return success
def M1_dout5(self, name, value):
success = self.mcu.digitalOut5(str(value))
if success:
self.sendtodb(name, str(value), 0)
#return True/False
return success
def M1_relay2(self, name, value):
success = self.mcu.relay2(value)
if success:
self.sendtodb(name, str(value), 0)
#return True/False
return success
def M1_relay1(self, name, value):
success = self.mcu.relay1(value)
if success:
self.sendtodb(name, str(value), 0)
#return True/False
return success
else:
return False
def M1_reboot(self, name, value):
self.sendtodb("log", "success rebooting", 0)
time.sleep(5)
os.system("reboot")
def M1_geo1p(self, name, value):
self.addGeo_point(1,value)
self.sendtodb(name, value, 0)
return True
def M1_geo1d(self, name, value):
self.addGeo_distance(1, value)
self.sendtodb(name, value, 0)
return True
def M1_rs232baud(self, name, value):
try:
success = self.mcu.set232Baud(int(value))
self.sendtodb("rs232baud", str(value), 0)
except:
success = False
return success
def M1_din2_fw(self, name, value):
#update digital in 2 forwarding rules
#"cloop":{"on":"off","deviceName":"M1","channel":"cloop","unitNum":"1"},
data = value.split(",")
self.dioForward["din2"]["on"] = data[0]
self.dioForward["din2"]["deviceName"] = data[1]
self.dioForward["din2"]["channel"] = data[2]
self.dioForward["din2"]["unitNum"] = data[3]
def updateDIOForward(self, name, value):
data = value.split(",")
name2 = name.split("-")[1]
self.dioForward[name2]["on"] = data[0]
self.dioForward[name2]["deviceName"] = data[1]
self.dioForward[name2]["channel"] = data[2]
self.dioForward[name2]["unitNum"] = data[3]
#update persistant dictionary
with open('/root/python_firmware/drivers/dioForward.p', 'wb') as handle:
pickle.dump(self.dioForward, handle)
self.sendtodb(name, value, 0)
return True
def M1_loc_change(self, name, value):
data = value.split(",")
if len(data) != 3:
return "wrong number of values sent, must be exactly 3"
{ "on":"off","mode":"forward","mac":None}
self.locSpoof["on"] = data[0].lower()
self.locSpoof["mode"] = data[1].lower()
self.locSpoof["mac"] = data[2].upper()
#update persistant dictionary
with open('/root/python_firmware/drivers/locSpoof.p', 'wb') as handle:
pickle.dump(self.locSpoof, handle)
self.sendtodb("loc_change", value, 0)
return True
def M1_rs232(self, name, value):
self.mcu.rs232.write(str(value))
return True
def RS232Thread(self):
while True:
data = self.mcu.rs232.read()
if len(data) > 2:
self.sendtodb("rs232", str(data), 0)
time.sleep(1)
def get_eoln(self):
eoln = SettingsBase.get_setting(self, "eoln")
if eoln is None:
return None
if eoln != self.__eoln_save:
# cache result to avoid repeat processing of escapes
self.__eoln_save = eoln
self._eoln = strip_escapes(eoln)
return self._eoln
def addGeo_distance(self, number, distance):
#self.geoData = {
# 1: {"lat":"342.3243,
# "long":"343.423",
# "distance":43
# }
if self.geoData.has_key(int(number)):
self.geoData[int(number)]["distance"] = float(distance)
else:
self.geoData[int(number)] = {"distance":"", "lat":"", "long":"", "alarm":""}
self.geoData[int(number)]["distance"] = float(distance)
#update persistant dictionary
with open('/root/python_firmware/drivers/geoData.p', 'wb') as handle:
pickle.dump(self.geoData, handle)
def syncGeoTags(self):
for number in self.geoData:
self.sendtodb(("geo" + str(number) + "p"), (self.geoData[number]["lat"] + "," + self.geoData[number]["long"]), 0)
self.sendtodb(("geo" + str(number) + "d"), (self.geoData[number]["distance"]), 0)
def addGeo_point(self, number, point):
#self.geoData = {
# 1: {"lat":"342.3243,
# "long":"343.423",
# "distance":43
# }
if self.geoData.has_key(int(number)):
self.geoData[int(number)]["lat"] = point.split(",")[0]
self.geoData[int(number)]["long"] = point.split(",")[1]
else:
self.geoData[int(number)] = {"distance":"", "lat":"", "long":"", "alarm":""}
self.geoData[int(number)]["lat"] = point.split(",")[0]
self.geoData[int(number)]["long"] = point.split(",")[1]
#update persistant dictionary
with open('/root/python_firmware/drivers/geoData.p', 'wb') as handle:
pickle.dump(self.geoData, handle)
def int32(self, x):
if x>0xFFFFFFFF:
raise OverflowError
if x>0x7FFFFFFF:
x=int(0x100000000-x)
if x<2147483648:
return -x
else:
return -2147483648
return x
def byteSwap32(self, array):
#array is a list of 2 dec numbers
newVal = ""
for i in array:
i = hex(i).replace('0x', '')
while len(i) < 4:
i = "0" + i
print i
newVal = i + newVal
print newVal
return struct.unpack('!f', newVal.decode('hex'))[0]
def byteArray(self, val, l=16, bs=False):
val = ''.join(format(val, '02x'))
val = str(val)
while len(val) < (l/4):
val = "0" + val
if bs:
val = val[(len(val)/2):] + val[:(len(val)/2)]
print val
bitStr = bin(int(val, base=16)).replace('0b', '')[::-1]
while len(bitStr) < l:
bitStr = bitStr + "0"
print bitStr
return bitStr
def M1_fileloc(self, name, value):
#@root@python_firmware@main.py,@root@python_firmware@main.py
try:
spiderFile = value.split(",")[0]
flyFile = value.split(",")[1]
self.flyFileLocation = flyFile.replace("@", "/")
self.sendtodb("log", "starting file transfer", 0)
#wait for the data to send, then wait a little more
thread.start_new_thread(self.waitforq, (spiderFile,))
except Exception,e:
print e
def waitforq(self, spiderFile):
print "starting to wait"
while self.q.qsize() > 0:
print "This is the size of the Q"
print self.q.qsize()
time.sleep(3)
print "ending long wait"
self.sendtodb("startfile", spiderFile, 0)
time.sleep(15)
self.M1_getfile('n','n')
def M1_uartsoc(self, name, value):
#on,ip,port
on = value.split(",")[0]
ip = value.split(",")[1]
port = value.split(",")[2]
if on.lower() == "on":
#clear old thread if its running:
self.runUartSocket = False
time.sleep(5)
self.runUartSocket = True
thread.start_new_thread(self.startUartSoc, (ip, port))
else:
self.runUartSocket = False
return True
def startUartSoc(self, ip, port):
print "thread started for socket"
self.mcu.xbee.fileTransfer = True
while self.runUartSocket:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (ip, int(port))
sock.connect(server_address)
try:
while self.runUartSocket:
data = self.mcu.xbee.read()
if data != "":
print "sending data"
sock.sendall(data)
time.sleep(1)
else:
time.sleep(2)
except Exception, e:
print e
time.sleep(5)
except Exception, e:
print e
time.sleep(5)
self.mcu.xbee.fileTransfer = False
def M1_getfile(self, name, value):
self.mcu.xbee.fileTransfer = True
#clear xbee
self.mcu.xbee.read()
modem = XMODEM(self.getc, self.putc)
stream = file('/tmp/output', 'wb')
try:
success = (modem.recv(stream, retry=60))
except Exception,e:
self.mcu.xbee.fileTransfer = False
print e
success = None
print success
self.mcu.xbee.fileTransfer = False
if success != None:
stream.close()
f = open("/tmp/output", "rb")
data = f.read()
data = zlib.decompress(data)
f.close()
final = open(self.flyFileLocation, "wb")
final.write(data)
final.close()
self.sendtodb("log", "file trasfer success", 0)
else:
self.sendtodb("log", "file transfer failed", 0)
def getc(self, size, timeout=300):
timeout = timeout * 10
data = self.lastData
count = 0
while len(data) < size:
count += 1
time.sleep(.1)
data += self.mcu.xbee.read()
if count > timeout and len(data) == 0:
return None
elif count > timeout:
self.lastData = ""
return data
sndData = data[0:size]
self.lastData = data[size:]
print "here is the data ", sndData
return sndData
def putc(self, data, timeout=10):
self.mcu.xbee.write(data)
return len(data)
def process_pulses(self, pulses, multiplier):
#load stored pulse data if we don't have any pulse data
if self.pulses is None:
try:
with open('/root/python_firmware/drivers/pulses.p', 'rb') as handle:
self.pulses = pickle.load(handle)
print "found pickled pulses Data"
print self.pulses
if ( self.pulses["reset-flag"] == 1 ): #if the reset flag is set, reset the total count
self.pulses["lr"] = 0
self.pulses["tr"] = 0
self.pulses["reset-flag"] = 0
self.sendtodb("reset-pulse", str(self.pulses["reset-flag"]), 0)
with open('/root/python_firmware/drivers/pulses.p', 'wb') as handle:
pickle.dump(self.pulses, handle)
print "pickled pulse data reset"
except:
print "couldn't load pulses from pickle"
self.pulses = {"tr":0, "lr":0, "reset-flag":0}
with open('/root/python_firmware/drivers/pulses.p', 'wb') as handle:
pickle.dump(self.pulses, handle)
#grab the initial usage and add it to the other saved totals totals
try:
#determine how much to add to the total
if self.pulses["lr"] <= pulses:
print "pulses increased"
#add the amount it increased to the total
self.pulses["tr"] += (pulses - self.pulses["lr"])
else:
#on level decreasing, we can assume the modem has reset,
self.pulses["tr"] += pulses
#replace last known amount with new one
self.pulses["lr"] = pulses
val = str(int(self.pulses['tr']) * multiplier)
item = "pulse"
if self.dioForward[item]["on"].lower() == "on":
ch = self.dioForward[item]["unitNum"]
deviceName = self.dioForward[item]["deviceName"]
chName = self.dioForward[item]["channel"]
if self.locSpoof["on"].lower() == "on":
if self.locSpoof["mode"].lower() == "forward":
self.sendtodbLoc(ch, chName, val, 0, deviceName, self.locSpoof["mac"])
elif self.locSpoof["mode"].lower() == "copy":
self.sendtodbLoc(ch, chName, val, 0, deviceName, self.locSpoof["mac"])
self.sendtodb(item, val, 0)
else:
self.sendtodbDev(ch, chName, val, 0, deviceName)
self.sendtodb(item, val, 0)
else:
self.sendtodb(item, val, 0)
#self.sendtodb("pulse", val, 0)
#I need pulse multiplier
#don't write to flash too often, it will wear the flash out!!
#update persistant dictionary
with open('/root/python_firmware/drivers/pulses.p', 'wb') as handle:
pickle.dump(self.pulses, handle)
except Exception, e:
print "error pulses"
print e
time.sleep(60)
#add up totals and keep for persistance
def get_network_bytes(self):
#load stored 3g usage data
try:
with open('/root/python_firmware/drivers/3G_usage.p', 'rb') as handle:
self.usageData = pickle.load(handle)
print "found pickled 3g usage Data"
print self.usageData
except:
print "couldn't load 3g usage from pickle"
self.usageData = {"lr":0,"lt":0,"tr":0,"tt":0}
interface= "3g-3g"
#grab the initial usage and add it to the other saved totals totals
count = 240
writeCount = 20
while True:
count += 1
writeCount += 1
try:
for line in open('/proc/net/dev', 'r'):
if interface in line:
data = line.split('%s:' % interface)[1].split()
rx_bytes, tx_bytes = (data[0], data[8])
rx = float(rx_bytes) / 1000
tx = float(tx_bytes) / 1000
#determine how much to add to the total
if self.usageData["lr"] <= rx:
print "data received increased"
#add the amount it increased to the total
self.usageData["tr"] += (rx - self.usageData["lr"])
else:
#on level decreasing, we can assume the modem has reset, so add all of the data up until now
self.usageData["tr"] += rx
self.usageData["lr"] = rx
continue
#replace last known amount with new one
self.usageData["lr"] = rx
#determine how much to add to the total
if self.usageData["lt"] <= tx:
print "data sent increased"
#add the amount it increased to the total
self.usageData["tt"] += (tx - self.usageData["lt"])
else:
self.usageData["tt"] += tx
self.usageData["lt"] = tx
continue
#replace last known amount with new one
self.usageData["lt"] = tx
if count > 240:
count = 0
self.sendtodb("rx", str(self.usageData['tr']), 0)
self.sendtodb("tx", str(self.usageData['tt']), 0)
self.sendtodb("rxtx", str(self.usageData['tr'] + self.usageData['tt'] ), 0)
#don't write to flash too often, it will wear the flash out!!
if writeCount > 10:
writeCount = 0
#update persistant dictionary
with open('/root/python_firmware/drivers/3G_usage.p', 'wb') as handle:
pickle.dump(self.usageData, handle)
time.sleep(60)
except Exception, e:
print "error in 3g data usage"
print e
time.sleep(60)
#add up totals and keep for persistance
def M1_cutoff(self, name, value):
if value == "True" or value == "true" or value == "on" or value == "On" or value == "1" or value == 1:
self.mcu.cutAllDataOff = True
else:
self.mcu.cutAllDataOff = False
return True
def M1_setmask(self, name, value):
mask = value
#lets do some simple validation:
ip = ip.strip()
test = ip.split(".")
if len(test) == 4:
for i in test:
if int(i) < 256:
continue
else:
return False
cmd = "/sbin/uci get network.lan.netmask=" + mask
os.system(cmd)
os.system("/sbin/uci commit network")
os.system("/sbin/ifup lan")
self.sendtodb("setmask", mask, 0)
return True
else:
return False
def M1_setip(self, name, value):
ip = value
#lets do some simple validation:
ip = ip.strip()
test = ip.split(".")
if len(test) == 4:
for i in test:
if int(i) < 256:
continue
else:
return False
cmd = "/sbin/uci set network.lan.ipaddr=" + ip
os.system(cmd)
os.system("/sbin/uci commit network")
os.system("/sbin/ifup lan")
self.sendtodb("setip", ip, 0)
return True
else:
return False