def comm_with_slave(self, iotp_request, app_data): """ initiate the connection for first time. """ iotp_request_uci = iotp_request.initiate_connection(app_data) """ communicate with stave """ if iotp_request_uci[0] is 200: msg_frame = iotp_request.fn_prepare_slave_request() # """ Sending Request To IOTP Slave """ try: slave_obj = SLAVE_LIBRARY[iotp_request.selected_slave_id] # check if slave available or not if slave_obj.address[0] != '0.0.0.0': # send request to slave slave_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) slave_sock.setblocking(True) slave_sock.connect((slave_obj.address[0], 10701)) slave_sock.sendall(msg_frame + "\n") log("SLAVE IP:{} CMD >> {}".format(slave_obj.socket, msg_frame)) info = self.fn_client_read_line(slave_sock) slave_sock.close() log("SLAVE IP:{} RESPONSE << {}".format( slave_obj.socket, info)) else: raise Exception('Slave Offline') except Exception, e: print e log_error(e) info = json.dumps({ 'status_code': 503, 'status_text': 'Slave offline', 'message': e.message })
def start_server(self): if self.connection_status is not True or self.handshake_done is not True: return False if self.slave_server is None: self.start_blinking() # bind socket with IP and PORT try: port = int(IOTP_SLAVE_CONF[KEY_PORT]) log("Creating Slave Listener @ PORT{}...".format(port)) while True: try: self.slave_server = socket.socket( socket.AF_INET, socket.SOCK_STREAM) self.slave_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.slave_server.bind(('', port)) break except Exception, e: log_error(e) time.sleep(1) # start listing to the incoming connection log('Slave Listener is running OK.') self.stop_blinking() self.s_listen() return True except Exception, e: log_error(e) return False
def iptp_stop(options=()): global bServer_status global iotp_server if bServer_status is True: log("Closing server...", False) bServer_status = False iotp_server.StatusLED.on() log("Server is closed.", False)
def handle_ping_incoming(incoming_conn, addr, client_data): try: incoming_conn.send("{},{}\n".format(PING_REPLY, client_data[7:])) log("App IP:{} | PING OK >> {},{}".format(addr, PING_REPLY, client_data[7:])) incoming_conn.close() except Exception, e: log_error(e) pass
def handle_iotp_incoming(self, iotp_request, app_socket, app_data, addr): # comm. with slave response_json_string = self.comm_with_slave(iotp_request, app_data) try: # log("CLIENT [IOTP] IP:{} | RESPONSE OK >> {}".format(addr, response_json_string)) # response to App app_socket.send("{}\n".format(response_json_string)) log("App IP:{} | RESPONSE - {}".format(addr, response_json_string)) except socket.error, e: print e log("App IP:{} | RESPONSE ERROR - {}".format(addr, e.message)) log_error(e)
def s_listen(self): BACK_LOG = 1 # listen for new incoming connection self.slave_server.listen(BACK_LOG) while True: log("WAIT FOR CMD...") # accept a new connection conn, addr = self.slave_server.accept() self.sts_blink = True start_new_thread(self.blink, (0, )) self.sts_blink = False start_new_thread(self.command_process, ( conn, addr, ))
def init_connection(self): if self.init_ok is not True: return False server_ip = str(IOTP_SLAVE_CONF[KEY_HOST_IP]) port = int(IOTP_SLAVE_CONF[KEY_HOST_PORT]) # self.server_offline_detection_timer.stop_timer() # self.server_offline_detection = False log("Connecting to server @{}...".format((server_ip, port))) while True: self.start_blinking() try: server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.setblocking(True) server_sock.settimeout(1) server_sock.connect((server_ip, port)) self.connection_status = True log("Connection.OK.") # stop blinking self.stop_blinking() break except Exception, e: print e self.connection_status = False log_error(e) log("Check HOST IP in configuration or HOST power") time.sleep(self.conn_retry_sec - 1) pass
def start(self): # log("Try starting...", False) if self.server_conf_status is False: log("CONF FAIL.", False) return False if self.server is None: log("CONF OK.", False) # configure the socket for blink_once the IOTP server # bind socket with IP and PORT try: log("Server IP " + self.HOST) # log("Server PORT " + str(self.PORT)) log("Creating server...", False) while True: try: self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server.bind((self.HOST, self.PORT)) break except socket.error, e: log_error(e) print e time.sleep(1) # blink_once listing to the incoming connection self.StatusLED.blink(closing_value=0) start_new_thread(self.socket_listener, ()) log('SERVER OK.RUNNING.', False) # self.StatusLED.stop_blink(0) """ START Thread FOR CLOUD SERVICE """ start_new_thread(self.start_cloud_service, ()) return True except socket.error, e: log_error(e) print e return False
def iotp_start(server_home, options=()): global bServer_status global iotp_server if bServer_status is False: log("Starting server...", False) # initialize request handler class iotp_req = iotp_req_handle.IOTPClientRequestHandler() # initialize server object if len(options) == 1: iotp_server = int_serve.IOTPServerCore(iotp_req, server_home, int(options[0])) else: iotp_server = int_serve.IOTPServerCore(iotp_req, server_home) # blink_once server s = iotp_server.start() if s is True: bServer_status = True log("Server is started", False) else: return False else: log("Server already running.", False) return True
def _communicate(self, in_server_conn, server_data): # read data from server log("RX: {}".format(server_data)) # if data available if server_data is not "" and server_data is not None: try: iotp_response = IOTPTransactionResponse( 400, IOTP_SLAVE_CONF[KEY_SLAVE_ID]) iotp_request = IOTPTransactionData( server_data, IOTP_SLAVE_CONF[KEY_SLAVE_ID]) # command request if iotp_request.get_trans_type_id( ) is IOTPTransactionData.RequestType.COMMAND: # process server data C 0001 0014 1 D 2 0001 r = IOTPTransactionTypeCommand(iotp_request) while r.has_next(): inf = r.next_operand_info() operand_type = inf[INDEX_OPERAND_TYPE] operand_id = inf[INDEX_OPERAND_ID] operation = inf[INDEX_OPERATION] try: """ Search PIN """ HWConf = None for k in range(0, len(HARDWARE_CONF)): hw_c = HARDWARE_CONF[k] if hw_c is not None and hw_c[ INDEX_OPERAND_ID] is operand_id: """ PIN Found """ HWConf = hw_c self.save_to_database( operand_id, operation) break if HWConf is None: iotp_response.set_status(405) break else: pin_type = HWConf[INDEX_OPERAND_TYPE] if pin_type == operand_type: pin = HWConf[INDEX_GPIO] if pin_type == DIGITAL_OPERAND_TYPE: # Change the operation value as the relays are active low if operation is 0: operation = 1 else: operation = 0 # Perform Digital Operation operate_gpio_digital(pin, operation) iotp_response.set_status(200) pass elif pin_type == ANALOG_OPERAND_TYPE: # Perform Analog Operation operate_gpio_analog(pin, operation) iotp_response.set_status(200) pass except RuntimeError, e: print e log_error(e) iotp_response.set_status(500) iotp_response.set_message(e.message) break # interrogation request elif iotp_request.get_trans_type_id( ) is IOTPTransactionData.RequestType.INTERROGATION: # process server data D 0001 0014 D # process server data D 0001 0014 C intr = IOTPTransactionTypeInterrogation(iotp_request) if intr.is_connection_check(): iotp_response.set_status(200) pass elif intr.is_status_check(): status = [] for k in range(0, len(HARDWARE_CONF)): hw_c = HARDWARE_CONF[k] if hw_c is not None: sts = get_gpio_status(hw_c[INDEX_GPIO]) if sts is 0: sts = 1 else: sts = 0 status.append({ "id": hw_c[INDEX_OPERAND_ID], "type": hw_c[INDEX_OPERAND_TYPE], "state": sts }) iotp_response.set_status(200) iotp_response.set_message(status) pass pass log("TX: {}\\n".format(iotp_response.get_json())) in_server_conn.sendall(iotp_response.get_json() + "\n")
def init_slave(self): KEY = 0 VALUE = 1 doc_calculated = 0 aoc_calculated = 0 log("IN CONFIG...") conf_file_path = CONF_DIR + '/iotp.slaveconf' c_file = open(conf_file_path) # load the configuration to memory for line in c_file: # skip comments if line[0] is "#": continue components = line.split("=", 1) if len(components) > 1: # skip comments inside values key = components[KEY].strip(" ").rstrip("\n") value = components[VALUE].split("#", 1)[0].strip(" ").rstrip("\n") IOTP_SLAVE_CONF[key] = value # validate configuration file while True: if self.fn_validate_conf_file() is False: self.status_code = 1 # mandatory key not found break digital_operand_count = int( IOTP_SLAVE_CONF[KEY_DIGITAL_OPERAND_COUNT]) analog_operand_count = int( IOTP_SLAVE_CONF[KEY_ANALOG_OPERAND_COUNT]) if (digital_operand_count + analog_operand_count) < 1: self.status_code = 2 # no operand found break if (digital_operand_count + analog_operand_count) > 8: self.status_code = 3 # Maximum 8 operand can be configured break if analog_operand_count > 2: self.status_code = 4 # 2 analog operand can be configured break for k in range(0, len(HARDWARE_CONF)): # check if digital operand try: gpio = IOTP_SLAVE_CONF[KEY_DIGITAL_OPERAND_PREFIX + str(k + 1)] if gpio is not None: HARDWARE_CONF[k] = (DIGITAL_OPERAND_TYPE, (k + 1), int(gpio)) doc_calculated += 1 self.digital_operand_list += "d{},".format(k + 1) continue except Exception, e: pass # check if analog operand try: gpio = IOTP_SLAVE_CONF[KEY_ANALOG_OPERAND_PREFIX + str(k + 1)] if gpio is not None: HARDWARE_CONF[k] = (ANALOG_OPERAND_TYPE, (k + 1), int(gpio)) aoc_calculated += 1 self.analog_operand_list += "a{},".format(k + 1) continue except Exception, e: pass
# blink_once listing to the incoming connection self.StatusLED.blink(closing_value=0) start_new_thread(self.socket_listener, ()) log('SERVER OK.RUNNING.', False) # self.StatusLED.stop_blink(0) """ START Thread FOR CLOUD SERVICE """ start_new_thread(self.start_cloud_service, ()) return True except socket.error, e: log_error(e) print e return False else: log("SOCKET FAIL.") return False def socket_listener(self): # listen for new incoming connection self.server.listen(self.BACK_LOG) while True: # accept a new connection conn, addr = self.server.accept() # blink_once a thread with client request # start_new_thread(self.blink_once, (0,)) start_new_thread(self.client_thread, (conn, addr, IOTPRequest())) self.StatusLED.on() time.sleep(0.1)
def init_server_conf(self): log("CONF IN PROGRESS...", False) try: json_path = self.server_home + '/iotp.json' # log("Opening configuration JSON @ " + json_path, False) j_file = open(json_path) JSON = json.load(j_file, "ASCII") # log(JSON) keys = ('copyright', 'date', 'author', 'name', 'master-id', 'id', 'username', 'password', 'gateway') for k in keys: SERVER_JSON_CONF[k] = copy.copy(JSON[k]) slave_group_json_arr = JSON["slave-group"] if not isinstance(slave_group_json_arr, list): raise KeyError slave_group_list = [] # Loop Each Slave Group # debug_ctr1 = 0 for group_json_obj in slave_group_json_arr: # debug_ctr1 += 1 # log(debug_ctr1) group_dict = { "name": group_json_obj['name'], 'id': group_json_obj['id'] } # get all slaves slave_json_arr = group_json_obj["slaves"] if not isinstance(slave_json_arr, list): raise KeyError slave_list = [] # Loop Each Slave # debug_ctr2 = 0 for slave_json_obj in slave_json_arr: # debug_ctr2 += 1 # log(str(debug_ctr1) + "," + str(debug_ctr2)) slave_dict = { "name": slave_json_obj['name'], 'id': slave_json_obj['id'], 'image_uri': slave_json_obj['image_uri'] } # get all operands operand_json_arr = slave_json_obj["operands"] if not isinstance(operand_json_arr, list): raise KeyError operand_list = [] do_list = [] ao_list = [] # Loop Each Slave Operand # debug_ctr3 = 0 for operand_json_obj in operand_json_arr: # debug_ctr3 += 1 # log(str(debug_ctr1) + "," + str(debug_ctr2) + "," + str(debug_ctr3)) operand_dict = { "name": operand_json_obj['name'], 'id': operand_json_obj['id'], 'state': operand_json_obj['state'] } operand_list.append(operand_dict) if str(operand_json_obj["type"]) == 'd': do_list.append("d{}".format( operand_json_obj["id"])) if str(operand_json_obj["type"]) == 'a': ao_list.append("a{}".format( operand_json_obj["id"])) slave_dict['operands'] = operand_list slave_list.append(slave_dict) # save th slave configuration SLAVE_LIBRARY[int(slave_json_obj["id"])] = IOTPSlaveInfo( int(slave_json_obj["id"]), do_list, ao_list) group_dict['slaves'] = slave_list slave_group_list.append(group_dict) # Slave count check SERVER_JSON_CONF['slave-group'] = slave_group_list self.server_conf_status = True j_file.close() except KeyError, e: # clear all configuration as there is an error log_error(e.message) SLAVE_LIBRARY.clear() self.server_conf_status = False
def start_cloud_service(self): # step 1: login # step 2: if session available else login # step 3: read for command # step 4: execute command # step 5: if session available else login # step 6: write command status # step 1: login # Always send a "User-Agent": "IOTP" header in request # the username and password would be found in iotp.json file while True: self.StatusLED.blink(mode="fast", retention="short", closing_value=0) try: log("Cloud Signing...") token = self.cloud_signing() if token is False: log("oops! login failed.") time.sleep(OPR_WAIT_SEC) continue log("Login OK") log("Waiting for HTTP CMDs...") while True: # step 2: if session available else login # step 3: read for command cmd_list = self.read_pending_cloud_cmd(token) if cmd_list == HTTP_UNAUTHORIZED: log("oops! session expired.") break if cmd_list is not False: self.StatusLED.on() time.sleep(0.1) self.StatusLED.off() # get the command count command_count = len(cmd_list) # get the latest command & ignore other commands if command_count > 0: # update command status to IN_EXE for c in cmd_list: log("Updating CMDs status to IN_EXE...", True) try: params = urllib.urlencode({ 'cmd_time': c['cmd_time'], 'status': 'IN_EXE' }) headers = { "Content-type": "application/x-www-form-urlencoded", "Accept": "application/json", "User-Agent": "IOTP", "S4AUTH": token, } conn = httplib.HTTPConnection(CLOUD_HOST) conn.request( "PUT", self.prepare_url("iotp-commands"), params, headers) response = conn.getresponse() # print response.read() pass except Exception, e: log_error(e) pass # get the last command last_cmd = cmd_list[command_count - 1] log("Executing HTTP CMD...") req = IOTPRequest() req.set_type(IOPTServiceType.HTTP) response_json_string = self.handle_http( req, last_cmd['command']) # update command status and value log("Updating CMD to ACK_EXE...", True) status = self.update_pending_cloud_cmd_status( last_cmd['cmd_time'], token, response_json_string) if status == HTTP_UNAUTHORIZED: log("oops! session expired.") break log("Waiting for HTTP CMDs...") time.sleep(OPR_WAIT_SEC) pass # cmd fetch & exe loop # self.StatusLED.stop_blink(0) except Exception, e: log_error(e) pass # any exception time.sleep(OPR_WAIT_SEC)
class IOTPSlave: def __init__(self, slave_home): global SLEEP_WAIT time.sleep(SLEEP_WAIT) self.StatusLED = S4LED(STATUS_LED_GPIO) self.init_ok = False # self.slave_home = slave_home self.connection_status = False self.handshake_done = False self.status_code = 0 self.slave_server = None self.digital_operand_list = "" self.analog_operand_list = "" self.conn_retry_sec = 5 self.sts_blink = False self.blink_pause = 0.2 # start blinking self.start_blinking() self.DB = DatabaseManager.Database(DB_DIR + "/s4.db") pass @staticmethod def fn_validate_conf_file(): key_map = (KEY_HOST_IP, KEY_SLAVE_ID, KEY_STATUS_LED, KEY_HOST_PORT, KEY_PORT, KEY_ANALOG_OPERAND_COUNT, KEY_DIGITAL_OPERAND_COUNT) for k in key_map: if k not in IOTP_SLAVE_CONF: return False return True def init_slave(self): KEY = 0 VALUE = 1 doc_calculated = 0 aoc_calculated = 0 log("IN CONFIG...") conf_file_path = CONF_DIR + '/iotp.slaveconf' c_file = open(conf_file_path) # load the configuration to memory for line in c_file: # skip comments if line[0] is "#": continue components = line.split("=", 1) if len(components) > 1: # skip comments inside values key = components[KEY].strip(" ").rstrip("\n") value = components[VALUE].split("#", 1)[0].strip(" ").rstrip("\n") IOTP_SLAVE_CONF[key] = value # validate configuration file while True: if self.fn_validate_conf_file() is False: self.status_code = 1 # mandatory key not found break digital_operand_count = int( IOTP_SLAVE_CONF[KEY_DIGITAL_OPERAND_COUNT]) analog_operand_count = int( IOTP_SLAVE_CONF[KEY_ANALOG_OPERAND_COUNT]) if (digital_operand_count + analog_operand_count) < 1: self.status_code = 2 # no operand found break if (digital_operand_count + analog_operand_count) > 8: self.status_code = 3 # Maximum 8 operand can be configured break if analog_operand_count > 2: self.status_code = 4 # 2 analog operand can be configured break for k in range(0, len(HARDWARE_CONF)): # check if digital operand try: gpio = IOTP_SLAVE_CONF[KEY_DIGITAL_OPERAND_PREFIX + str(k + 1)] if gpio is not None: HARDWARE_CONF[k] = (DIGITAL_OPERAND_TYPE, (k + 1), int(gpio)) doc_calculated += 1 self.digital_operand_list += "d{},".format(k + 1) continue except Exception, e: pass # check if analog operand try: gpio = IOTP_SLAVE_CONF[KEY_ANALOG_OPERAND_PREFIX + str(k + 1)] if gpio is not None: HARDWARE_CONF[k] = (ANALOG_OPERAND_TYPE, (k + 1), int(gpio)) aoc_calculated += 1 self.analog_operand_list += "a{},".format(k + 1) continue except Exception, e: pass if digital_operand_count is not doc_calculated or analog_operand_count is not aoc_calculated: self.status_code = 5 # number of operand and PIN configuration does not matched break self.digital_operand_list = self.digital_operand_list.rstrip(",") self.analog_operand_list = self.analog_operand_list.rstrip(",") # configure GPIO for HW operations for k in range(0, len(HARDWARE_CONF)): pin = HARDWARE_CONF[k] if pin is not None: init_gpio(pin[INDEX_GPIO], 'O', 0) self.init_ok = True log("CONFIG OK.") break # while loop
import os import time import IOTP_CommandLine.commands as cmd from IntsUtil import util from IntsUtil.util import log _author_ = "int_soumen" _date_ = "2019-JAN-03" if __name__ == "__main__": _version_ = "2.5.11" log("Welcome to IOTP server version " + _version_, False) try: if cmd.iotp_start(util.HOME_DIR): while True: time.sleep(10000) pass except KeyboardInterrupt, e: cmd.iptp_stop() pass log("EXIT.", False)
self.digital_operand_list = self.digital_operand_list.rstrip(",") self.analog_operand_list = self.analog_operand_list.rstrip(",") # configure GPIO for HW operations for k in range(0, len(HARDWARE_CONF)): pin = HARDWARE_CONF[k] if pin is not None: init_gpio(pin[INDEX_GPIO], 'O', 0) self.init_ok = True log("CONFIG OK.") break # while loop if self.init_ok is not True: log("CONFIG FAILED.") self.blink_pause = 1 self.start_blinking() def start_blinking(self): global blink_level if self.sts_blink is False: blink_level = (blink_level + 1) self.sts_blink = True start_new_thread(self.blink, (1, )) pass def stop_blinking(self, closing_value=0): global blink_level if blink_level > 0: blink_level = (blink_level - 1)
def iptp_stat(options=()): global bServer_status if bServer_status is True: log("Server is online.", False) else: log("Server is closed.", False)
import os import time from IOTPSlaveCore.IOTPSlave import IOTPSlave from IntsUtil import util from IntsUtil.util import log _author_ = "int_soumen" _date_ = "16-Dec-2018" # IOTP Slave Service. # This service run on slave HW to operate relays and analog outputs if __name__ == "__main__": _version_ = "3.5.0" log("Welcome to IOTP Slave version " + _version_) slave_home = os.path.dirname(os.path.realpath(__file__)) slave = IOTPSlave(slave_home) slave.init_slave() try: while True: if slave.init_connection() is True: if slave.start_server() is True: break time.sleep(5) while True: time.sleep(5000) except KeyboardInterrupt, e: slave.stop() pass