diff --git a/Agents/DeviceDiscoveryAgent/devicediscovery/agent.py b/Agents/DeviceDiscoveryAgent/devicediscovery/agent.py index 1b1fd1eb146ea0e1d1e36befe8bc2effa7eb3791..32481824fc582c4d161a060b5bccc1000682fe7f 100755 --- a/Agents/DeviceDiscoveryAgent/devicediscovery/agent.py +++ b/Agents/DeviceDiscoveryAgent/devicediscovery/agent.py @@ -99,6 +99,7 @@ def DeviceDiscoveryAgent(config_path, **kwargs): findWiFiWeMo = settings.FIND_DEVICE_SETTINGS['findWiFiWeMo'] findBACnet = settings.FIND_DEVICE_SETTINGS['findBACnet'] findModbus = settings.FIND_DEVICE_SETTINGS['findModbus'] + findSerial = settings.FIND_DEVICE_SETTINGS['findSerial'] # @paths PROJECT_DIR = settings.PROJECT_DIR @@ -125,6 +126,7 @@ def DeviceDiscoveryAgent(config_path, **kwargs): self.findWiFiWeMo = findWiFiWeMo self.findBACnet = findBACnet self.findModbus = findModbus + self.findSerial = findSerial self.discovery_list = list() @@ -144,6 +146,8 @@ def DeviceDiscoveryAgent(config_path, **kwargs): if self.findModbus: self.discovery_list.append('VC1000') self.discovery_list.append('M1000') + if self.findSerial: + self.discovery_list.append('Tekmar Bypass Controller') self.new_discovery=True self.no_new_discovery_count=0 @@ -249,7 +253,7 @@ def DeviceDiscoveryAgent(config_path, **kwargs): print "{} >> is finding available {} {} devices ...".format(agent_id,com_type,discovery_type) discovery_module = importlib.import_module("DeviceAPI.discoverAPI."+com_type) - if (com_type == 'BACnet'): + if (com_type == 'BACnet') or (com_type == 'Serial'): discovery_returns_ip = False else: discovery_returns_ip = True diff --git a/Agents/PlugloadAgent/plugload/agent.py b/Agents/PlugloadAgent/plugload/agent.py index dd7a92ef3c9359cd008f81066b632ada026321ae..5f24ec5f20adad27efb8a5a1fd764bd24d721730 100755 --- a/Agents/PlugloadAgent/plugload/agent.py +++ b/Agents/PlugloadAgent/plugload/agent.py @@ -212,6 +212,11 @@ def PlugloadAgent(config_path, **kwargs): self.subscriptionTime=datetime.datetime.now() except Exception as er: print "Can't subscribe.", er + elif api == 'classAPI_Tekmar_Bypass': + try: + Plugload.setDeviceStatus({"active_control":"BEMOSS"}) + except Exception as er: + print "Couldn't take BEMOSS Control:", er def updatePostgresDB(self): try: @@ -259,7 +264,7 @@ def PlugloadAgent(config_path, **kwargs): #Checks if two value of variable is to be considered different. # Returns false if numerical value are different by less than the tolerance % if variable_name=='status': - return value1 == value2 #strict comparision for status + return (value1 != value2) #strict comparision for status elif variable_name in ['power','energy','offline_count']: if value1 == 0: return True if value2 != 0 else False @@ -268,7 +273,7 @@ def PlugloadAgent(config_path, **kwargs): self.changed_variables = dict() for v in log_variables: if v in Plugload.variables: - if v not in self.variables or isChanged(v, self.variables[v],Plugload.variables[v]): + if (v not in self.variables) or isChanged(v, self.variables[v],Plugload.variables[v]): self.variables[v] = Plugload.variables[v] self.changed_variables[v] = log_variables[v] else: @@ -495,30 +500,17 @@ def PlugloadAgent(config_path, **kwargs): print("ERROR: {} fails to update cassandra database".format(agent_id)) print er - def updateStatus(self,states=None): - - if states is not None: - print "got state change:",states - self.changed_variables = dict() - if(self.get_variable('status') != 'ON' if states['status']==1 else 'OFF'): - self.set_variable('status','ON' if states['status']==1 else 'OFF') - self.changed_variables['status'] = log_variables['status'] - if 'power' in states: - if(self.get_variable('power') != states['power']): - self.changed_variables['power'] = log_variables['power'] - self.set_variable('power',states['power']) - + def updateStatus(self): + with threadingLock: + try: + cassandraDB.insert(agent_id,self.variables,log_variables) + print "cassandra success" + except Exception as er: + print("ERROR: {} fails to update cassandra database".format(agent_id)) + print er - with threadingLock: - try: - cassandraDB.insert(agent_id,self.variables,log_variables) - print "cassandra success" - except Exception as er: - print("ERROR: {} fails to update cassandra database".format(agent_id)) - print er - - self.updatePostgresDB() + self.updatePostgresDB() topic = '/agent/ui/'+device_type+'/device_status_response/'+_topic_Agent_UI_tail # now = datetime.utcnow().isoformat(' ') + 'Z' diff --git a/DeviceAPI/classAPI/classAPI_Tekmar_Bypass.py b/DeviceAPI/classAPI/classAPI_Tekmar_Bypass.py new file mode 100755 index 0000000000000000000000000000000000000000..06be976259a1f796fff3c04e2bcdbc8e7893181f --- /dev/null +++ b/DeviceAPI/classAPI/classAPI_Tekmar_Bypass.py @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- +''' +Copyright (c) 2017, BlocPower +All rights reserved. + +#__author__ = "Avijit Saha" +#__credits__ = "https://github.com/superalex/Python-RLY02" +#__version__ = "2.0" +#__maintainer__ = "Avijit Saha" +#__email__ = "avijit@blocpower.org" +#__website__ = "www.blocpower.io" +#__created__ = "2017-03-23 11:04:15" +#__lastUpdated__ = "2017-03-23 11:04:15" +''' + +'''This API class is for an agent that wants to control a boiler using Tekmar Bypass designed at BlocPower''' + +import json +import datetime +import serial +import time +from struct import * + +SERIAL_PATH = '/dev/ttyACM0' +BAUD_RATE = 9600 + +commands = { + 'relay_1_on': 0x65, + 'relay_1_off': 0x6F, + 'relay_2_on': 0x66, + 'relay_2_off': 0x70, + 'info': 0x5A, + 'relay_states': 0x5B, +} + + +def send_command(cmd, read_response=False): + ser = serial.Serial(SERIAL_PATH, BAUD_RATE) + ser.write(chr(cmd) + '\n') + response = read_response and ser.read() or None + ser.close() + return response + + +def turn_relay_1_on(): + send_command(commands['relay_1_on']) + + +def turn_relay_1_off(): + send_command(commands['relay_1_off']) + + +def turn_relay_2_on(): + send_command(commands['relay_2_on']) + + +def turn_relay_2_off(): + send_command(commands['relay_2_off']) + + +def get_relay_states(): + states = send_command(commands['relay_states'], read_response=True) + response = unpack('b', states)[0] + states = { + 0: {'1': False, '2': False}, + 1: {'1': True, '2': False}, + 2: {'1': False, '2': True}, + 3: {'1': True, '2': True}, + } + return states[response] + + +class API: + # 1. constructor : gets call every time when create a new class + # requirements for instantiation1. model, 2.api, 3. address + def __init__(self,**kwargs): # default color is white + # Initialized common attributes + self.variables = kwargs + self.debug = False + self.set_variable('connection_renew_interval',600) + self.listeningThread = None + self.set_variable('offline_count',0) + + + # Attributes from Attributes table + ''' + Attributes: + ------------------------------------------------------------------------------------------ + USB-RLY02 + active_control GET POST "Default" : Tekmar control, "BEMOSS" : BEMOSS control + status GET POST BEMOSS control status: "ON"/"OFF" + ------------------------------------------------------------------------------------------ + + ''' + + #Capabilites (methods) from Capabilities table + ''' + API available methods: + 1. getDeviceStatus() GET + 2. setDeviceStatus(postmsg) POST + 3. identifyDevice() + ''' + + + def set_variable(self,k,v): # k=key, v=value + self.variables[k] = v + + def get_variable(self,k): + return self.variables.get(k, None) # default of get_variable is none + + def renewConnection(self): + pass + + #GET device status by XML read + def getDeviceStatus(self): + print "----------------------------------------------------------------" + print "{0}Agent is querying its current status at {1} please wait ...".format(self.variables.get('agent_id',None), + datetime.datetime.now()) + getDeviceStatusResult = True + + try: + relay_states = get_relay_states() + if self.debug: print str(relay_states) + if '1' in relay_states.keys(): + if relay_states['1']: + self.set_variable('active_control', "BEMOSS") + else: + self.set_variable('active_control', "Default") + + if relay_states['2']: + self.set_variable('status', "ON") + else: + self.set_variable('status', "OFF") + else: + print "classAPI_Tekmar_Bypass: Couldn't get status" + if self.debug: self.printDeviceStatus() + except Exception as er: + getDeviceStatusResult = False + print("ERROR: classAPI_Tekmar_Bypass connection failure! @ getDeviceStatus") + print er + + if getDeviceStatusResult==True: + self.set_variable('offline_count',0) + else: + self.set_variable('offline_count',self.get_variable('offline_count')+1) + + def printDeviceStatus(self): + print("Currently Boiler Control is connected to "+self.get_variable('active_control')+" Control") + print("Status of BEMOSS Control is: "+self.get_variable('status')) + + #POST Change status + def setDeviceStatus(self, newstatus): + setDeviceStatusResult = True + + # Data conversion before passing to the device + _data = json.dumps(newstatus) + _data = json.loads(_data) + + try: + if 'active_control' in _data.keys(): + if _data['active_control'] == "Default": + send_command(commands['relay_1_off']) + elif _data['active_control'] == "BEMOSS": + send_command(commands['relay_1_on']) + else: + print("ERROR: classAPI_Tekmar_Bypass @ setDeviceStatus : Wrong Command") + setDeviceStatusResult = False + + if 'status' in _data.keys(): + if _data['status'] == "OFF": + send_command(commands['relay_2_off']) + elif _data['status'] == "ON": + send_command(commands['relay_2_on']) + else: + print("ERROR: classAPI_Tekmar_Bypass @ setDeviceStatus : Wrong Command") + setDeviceStatusResult = False + + except Exception as Er: + print("ERROR: classAPI_Tekmar_Bypass action failure @ setDeviceStatus") + print Er + setDeviceStatusResult = False + + return setDeviceStatusResult + + #Identify Device by Toggling device status twice + def identifyDevice(self): + identifyDeviceResult = False + try: + self.getDeviceStatus() + self.toggleDeviceStatus() + print(self.get_variable("model")+" is being identified with starting status "+str(self.get_variable('status'))) + self.timeDelay(5) + self.toggleDeviceStatus() + print("Identification for "+self.get_variable("model")+" is done with status "+str(self.get_variable('status'))) + identifyDeviceResult = True + except Exception as Er: + print("ERROR: classAPI_Tekmar_Bypass connection failure! @ identifyDevice") + print Er + + return identifyDeviceResult + + # ------------ Helper Methods ------------------------------------- + #GET current status and POST toggled status + def toggleDeviceStatus(self): + if self.get_variable('status') == "ON": + self.setDeviceStatus({"status":"OFF"}) + else: + self.setDeviceStatus({"status":"ON"}) + + # method6: time delay + def timeDelay(self,time_iden): # specify time_iden for how long to delay the process + t0 = time.time() + self.seconds = time_iden + while time.time() - t0 <= time_iden: + self.seconds = self.seconds - 1 + print("wait: {} sec".format(self.seconds)) + time.sleep(1) + # ----------------------------------------------------------------- + +# This main method will not be executed when this class is used as a module +def main(): + # Test Codes + + Boilercontrol = API(model='USB-RLY02', api='classAPI_TekMar_Bypass', address='/dev/ttyACM0', agent_id='plugloadagent') + + # Get and Print Device Status + Boilercontrol.getDeviceStatus() + print Boilercontrol.variables + # Boilercontrol.identifyDevice() + # Boilercontrol.setDeviceStatus({"active_control": "BEMOSS"}) + Boilercontrol.setDeviceStatus({"status": "OFF"}) + response = send_command(commands['info'],read_response=True) + print str(response) + +if __name__ == "__main__": main() \ No newline at end of file diff --git a/DeviceAPI/discoverAPI/Serial.py b/DeviceAPI/discoverAPI/Serial.py new file mode 100755 index 0000000000000000000000000000000000000000..12325ae563b9a878037628cf3d369325c1b88bab --- /dev/null +++ b/DeviceAPI/discoverAPI/Serial.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +''' +Copyright (c) 2017, BlocPower +All rights reserved. + +#__author__ = "Avijit Saha" +#__credits__ = "" +#__version__ = "2.0" +#__maintainer__ = "Avijit Saha" +#__email__ = "avijit@blocpower.org" +#__website__ = "www.blocpower.io" +#__created__ = "2017-03-23 11:04:15" +#__lastUpdated__ = "2017-03-23 11:04:15" +''' + +import re +import subprocess + +debug = True + +def discover_usb(): + device_re = re.compile("Bus\s+(?P\d+)\s+Device\s+(?P\d+).+ID\s(?P\w+:\w+)\s(?P.+)$", re.I) + df = subprocess.check_output("lsusb") + devices = [] + for i in df.split('\n'): + if i: + info = device_re.match(i) + if info: + dinfo = info.groupdict() + dinfo['device'] = '/dev/bus/usb/%s/%s' % (dinfo.pop('bus'), dinfo.pop('device')) + devices.append(dinfo) + + return devices + +def discover(type, timeout=2, retries=1): + responses = list() + usb_devices = discover_usb() + if debug: print usb_devices + + if type=='USB-RLY02': + for usb_device in usb_devices: + if usb_device['tag'] == 'Microchip Technology, Inc. Devantech USB-ISS': + responses.append(usb_device['id'].replace(':','')) + + return responses + +def getmodelvendor(type,address): + + if type=="USB-RLY02": + deviceModel = "Tekmar Bypass Controller" + deviceVendor = "BlocPower" + return {'model':deviceModel,'vendor':deviceVendor} + + +# This main method will not be executed when this class is used as a module +def main(): + print discover('USB-RLY02') + # print discover('thermostat') + #print getMACaddress('USB-RLY02','/dev/ttyACM0') + # print type(getMACaddress('Philips','http://192.168.102.:80')) + print getmodelvendor('USB-RLY02','/dev/ttyACM0') + +if __name__ == "__main__": main() diff --git a/bemoss_lib/utils/platform_initiator.py b/bemoss_lib/utils/platform_initiator.py index 4305c224dc29625330885d716f4d02e4e47a7615..d1955a7af3bc17f83a48832ac24571684c3343fe 100755 --- a/bemoss_lib/utils/platform_initiator.py +++ b/bemoss_lib/utils/platform_initiator.py @@ -354,6 +354,8 @@ cur.execute("INSERT INTO supported_devices VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s, ("M1000","Prolon","Modbus","rtu","Prolon_RTU","1RTU","classAPI_vav_rtu",False,False,4,4,True)) cur.execute("INSERT INTO supported_devices VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)", ("Insight","Belkin International Inc.","WiFi","plugload","WeMo","3WIS","classAPI_WeMo",True,False,4,4,True)) +cur.execute("INSERT INTO supported_devices VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)", + ("Tekmar Bypass Controller","BlocPower","Serial","plugload","USB-RLY02","3WSP","classAPI_Tekmar_Bypass",True,False,4,4,True)) conn.commit() print "Table supported_devices populated successfully!" diff --git a/settings.py b/settings.py index 3aeff6d56ade33b40cfce292ec44bf5d24492ce1..43d1a5d1448f29232d6b9ebc530e8ab25f639d6a 100755 --- a/settings.py +++ b/settings.py @@ -153,10 +153,10 @@ LANGUAGE_CODE = 'en-us' FIND_DEVICE_SETTINGS = { - 'findWiFi': True, - 'findWiFiHue': True, - 'findWiFiWeMo': True, - 'findBACnet': True, - 'findModbus': True, - + 'findWiFi': False, + 'findWiFiHue': False, + 'findWiFiWeMo': False, + 'findBACnet': False, + 'findModbus': False, + 'findSerial': True, }