def __init__(self, credentials): self.systemKey = credentials['systemKey'] self.systemSecret = credentials['systemSecret'] self.username = credentials['username'] self.password = credentials['password'] self.platformURL = credentials['platformURL'] self.gatewayAddress = self.GetMacAddress() #Connect to MQTT cbSystem = System(self.systemKey, self.systemSecret, self.platformURL) # Device Auth if 'active_key' in credentials: self.gatewayName = credentials["name"] self.active_key = credentials['active_key'] cbAuth = cbSystem.Device(self.gatewayName, credentials['active_key']) else: self.gatewayName = self.gatewayAddress cbAuth = cbSystem.User(credentials['username'], credentials['password']) # right now override the GatewayName so that portal demos work easier self.gatewayName = "thunderboard" self.client = cbSystem.Messaging(cbAuth) self.client.connect() # the on_connect is not working self.client.on_message = self.CommandCallback
return json.JSONEncoder.default(self, obj) CB_CONFIG = {} # Parse and Validate all args parse_env_variables(os.environ) parse_args(sys.argv) check_required_config() # System credentials CB_SYSTEM = System(CB_CONFIG['CB_SYSTEM_KEY'], CB_CONFIG['CB_SYSTEM_SECRET'], CB_CONFIG['httpURL'] + ":" + CB_CONFIG["httpPort"] ) uid = None if 'deviceID' in CB_CONFIG: uid = CB_SYSTEM.Device(CB_CONFIG['deviceID'], CB_CONFIG['activeKey']) elif 'CB_SERVICE_ACCOUNT' in CB_CONFIG: uid = CB_SYSTEM.Device(CB_CONFIG['CB_SERVICE_ACCOUNT'], authToken=CB_CONFIG['CB_SERVICE_ACCOUNT_TOKEN']) else: print("Device Name/Active Key or Device Service Account/Token not provided") exit(-1) mqtt = CB_SYSTEM.Messaging(uid, CB_CONFIG["messagingPort"], keepalive=30) # Set up callback function def on_connect(client, userdata, flags, rc): # When we connect to the broker, start publishing our data to the keelhauled topic print("Return Code: ", rc)
class AdapterLibrary: DEFAULT_LOG_LEVEL = "info" DEFAULT_PLATFORM_URL = "http://localhost:9000" DEFAULT_MESSAGING_URL = "localhost:1883" DEFAULT_ADAPTER_CONFIG_COLLECTION_NAME = "adapter_config" SYSTEM_KEY_ARG_KEY = "CB_SYSTEM_KEY" SYSTEM_SECRET_ARG_KEY = "CB_SYSTEM_SECRET" DEVICE_NAME_ARG_KEY = "device_name" ACTIVE_KEY_ARG_KEY = "active_key" SERVICE_ACCOUNT_ARG_KEY = "CB_SERVICE_ACCOUNT" SERVICE_ACCOUNT_TOKEN_ARG_KEY = "CB_SERVICE_ACCOUNT_TOKEN" PLATFORM_URL_ARG_KEY = "platform_URL" MESSAGING_URL_ARG_KEY = "messaging_URL" ADAPTER_CONFIG_COLLECTION_NAME_ARG_KEY = "adapter_config_collection_name" LOG_LEVEL_ARG_KEY = "log_level" def __init__(self, adapter_name): cbLogs.info("Initializing AdapterLibrary with adapter name: " + adapter_name) self.adapter_name = adapter_name self._args = {} self._cb_system = None self._device_client = None self._sub_topic = None self._cb_message_handler = None def parse_arguments(self): cbLogs.info("AdapterLibrary - parse_arguments - parsing environment variables and flags") self.__parse_env_variables() self.__parse_flags() self._args[self.LOG_LEVEL_ARG_KEY] = string.upper(self._args[self.LOG_LEVEL_ARG_KEY]) logging.basicConfig(level=self._args[self.LOG_LEVEL_ARG_KEY]) if self._args[self.LOG_LEVEL_ARG_KEY] != "DEBUG": cbLogs.DEBUG = False cbLogs.MQTT_DEBUG = False cbLogs.info("AdapterLibrary - parse_arguments - parsed adapter arguments: " + str(self._args)) cbLogs.info("AdapterLibrary - parse_arguments - Verifying required adapter arguments") if self.SYSTEM_KEY_ARG_KEY not in self._args: cbLogs.error("System Key is required, can be supplied with --systemKey flag or " + self.SYSTEM_KEY_ARG_KEY + " environment variable") exit(-1) if self.SYSTEM_SECRET_ARG_KEY not in self._args: cbLogs.error("System Secret is required, can be supplied with --systemSecret flag or " + self.SYSTEM_SECRET_ARG_KEY + " environment variable") exit(-1) if self.ACTIVE_KEY_ARG_KEY not in self._args and self.SERVICE_ACCOUNT_ARG_KEY not in self._args: cbLogs.error("Device Password is required when not using a Service Account, can be supplied with --password flag") exit(-1) if self.SERVICE_ACCOUNT_ARG_KEY in self._args and self.SERVICE_ACCOUNT_TOKEN_ARG_KEY not in self._args: cbLogs.error("Service Account Token is required when a Service Account is specified, this should have automatically been supplied. Check for typos then try again") exit(-1) cbLogs.info("AdapterLibrary - parse_arguments - Adapter arguments parsed and verified!") def initialize_clearblade(self): cbLogs.info("AdapterLibrary - initialize_clearblade - initializing with ClearBlade") self._cb_system = System(self._args[self.SYSTEM_KEY_ARG_KEY], self._args[self.SYSTEM_SECRET_ARG_KEY], self._args[self.PLATFORM_URL_ARG_KEY]) if self.SERVICE_ACCOUNT_ARG_KEY in self._args: self.__auth_with_service_account() else: self.__auth_with_device() return self.__fetch_adapter_config() def connect_MQTT(self, topic="", cb_message_handler=None): cbLogs.info("AdapterLibrary - connect_MQTT - Initializing the ClearBlade MQTT message broker") self._cb_message_handler = cb_message_handler self._cb_mqtt = self._cb_system.Messaging(self._device_client, client_id=self.adapter_name + "-" + str(random.randint(0, 10000))) self._cb_mqtt.on_connect = self.__on_MQTT_connect self._cb_mqtt.on_disconnect = self.__on_MQTT_disconnect if topic != "": self._cb_mqtt.on_subscribe = self.__on_MQTT_subscribe self._cb_mqtt.on_message = self.__on_MQTT_message_received self._sub_topic = topic self._cb_mqtt.connect() def publish(self, topic, message): cbLogs.info("AdapterLibrary - publish - Publishing MQTT message on topic " + topic) self._cb_mqtt.publish(topic, message) def disconnect_MQTT(self): cbLogs.info("AdapterLibrary - disconnect_MQTT - Disconnecting from ClearBlade MQTT message broker") self._cb_mqtt.disconnect() def __auth_with_service_account(self): cbLogs.info("AdapterLibrary - __auth_with_service_account - Authenticating as service account") self._device_client = self._cb_system.Device(self._args[self.SERVICE_ACCOUNT_ARG_KEY], authToken=self._args[self.SERVICE_ACCOUNT_TOKEN_ARG_KEY]) def __auth_with_device(self): cbLogs.info("AdapterLibrary - __auth_with_device - Authenticating as device") self._device_client = self._cb_system.Device(self._args[self.DEVICE_NAME_ARG_KEY], self._args[self.ACTIVE_KEY_ARG_KEY]) def __fetch_adapter_config(self): cbLogs.info("AdapterLibrary - __fetch_adapter_config - Retrieving adapter config") adapter_config = {"topic_root": self.adapter_name, "adapter_settings": ""} collection = self._cb_system.Collection(self._device_client, collectionName=self._args[self.ADAPTER_CONFIG_COLLECTION_NAME_ARG_KEY]) query = Query() query.equalTo("adapter_name", self.adapter_name) rows = collection.getItems(query) if len(rows) == 1: if rows[0]["topic_root"] != "": adapter_config["topic_root"] = str(rows[0]["topic_root"]) if rows[0]["adapter_settings"] != "": raw_json = json.loads(str(rows[0]["adapter_settings"])) adapter_config["adapter_settings"] = self.__byteify(raw_json) else: cbLogs.warn("No adapter config found for adapter name " + self.adapter_name + ". Using defaults") cbLogs.info("AdapterLibrary - __fetch_adapter_config - Using adapter config: " + str(adapter_config)) return adapter_config def __on_MQTT_connect(self, client, userdata, flags, rc): cbLogs.info("AdapterLibrary - __on_MQTT_connect - MQTT successfully connected!") if self._sub_topic != None: self._cb_mqtt.subscribe(self._sub_topic) def __on_MQTT_disconnect(self, client, userdata, rc): cbLogs.info("AdapterLibrary - __on_MQTT_disconnect - MQTT disconnected with rc " + str(rc)) if self._sub_topic != None and rc == 1: cbLogs.warn("AdapterLibrary - __on_MQTT_disconnect - Verify that your service account has permission to subscribe to the topic: " + self._sub_topic) def __on_MQTT_subscribe(self, client, userdata, mid, granted_qos): cbLogs.info("AdapterLibrary - __on_MQTT_subscribe - MQTT successfully subcribed to topic " + self._sub_topic) def __on_MQTT_message_received(self, client, userdata, message): cbLogs.info("AdapterLibrary - __on_MQTT_message_received - MQTT message received on topic " + message.topic) if self._cb_message_handler != None: cbLogs.info("calling message handler") self._cb_message_handler(message) def __parse_env_variables(self): """Parse environment variables""" env = os.environ possible_vars = [self.SYSTEM_KEY_ARG_KEY, self.SYSTEM_SECRET_ARG_KEY, self.SERVICE_ACCOUNT_ARG_KEY, self.SERVICE_ACCOUNT_TOKEN_ARG_KEY] for var in possible_vars: if var in env: cbLogs.info("Setting adapter arguments from environment variable: " + var + ": " + str(env[var])) self._args[var] = env[var] def __parse_flags(self): """Parse the command line arguments""" parser = argparse.ArgumentParser(description='ClearBlade Adapter') parser.add_argument('--systemKey', dest=self.SYSTEM_KEY_ARG_KEY, help='The System Key of the ClearBlade \ Plaform "System" the adapter will connect to.') parser.add_argument('--systemSecret', dest=self.SYSTEM_SECRET_ARG_KEY, help='The System Secret of the \ ClearBlade Plaform "System" the adapter will connect to.') parser.add_argument('--deviceName', dest=self.DEVICE_NAME_ARG_KEY, default=self.adapter_name, help='The name of the device that will be used for device \ authentication against the ClearBlade Platform or Edge, defined \ within the devices table of the ClearBlade platform. The default is ' + self.adapter_name) parser.add_argument('--password', dest=self.ACTIVE_KEY_ARG_KEY, help='The password (active key) of the device that will be used for device \ authentication against the ClearBlade Platform or Edge, defined within \ the devices table of the ClearBlade platform.') parser.add_argument('--platformURL', dest=self.PLATFORM_URL_ARG_KEY, default=self.DEFAULT_PLATFORM_URL, \ help='The HTTP URL of the ClearBlade Platform or Edge the adapter will \ connect to (including port if non-standard). The default is ' + self.DEFAULT_PLATFORM_URL) parser.add_argument('--messagingURL', dest=self.MESSAGING_URL_ARG_KEY, default=self.DEFAULT_MESSAGING_URL, \ help='The MQTT URL of the ClearBlade Platform or Edge the adapter will \ connect to (including port if non-standard). The default is ' + self.DEFAULT_MESSAGING_URL) parser.add_argument('--adapterConfigCollection', dest=self.ADAPTER_CONFIG_COLLECTION_NAME_ARG_KEY, \ default=self.DEFAULT_ADAPTER_CONFIG_COLLECTION_NAME, \ help='The name of the ClearBlade Platform data collection which contains \ runtime configuration settings for the adapter. The default is ' + self.DEFAULT_ADAPTER_CONFIG_COLLECTION_NAME) parser.add_argument('--logLevel', dest=self.LOG_LEVEL_ARG_KEY, default=self.DEFAULT_LOG_LEVEL, choices=['fatal', 'error', \ 'warn', 'info', 'debug'], help='The level of logging that \ should be utilized by the adapter. The default is ' + self.DEFAULT_LOG_LEVEL) args = vars(parser.parse_args(args=sys.argv[1:])) for var in args: if args[var] != "" and args[var] != None: cbLogs.info("Setting adapter arguments from command line argument: " + var + ": " + str(args[var])) self._args[var] = args[var] def __byteify(self, input): cbLogs.info("in byteify") # helper function for python 2.7 to convert unicode to strings in a dict created with json.loads # https://stackoverflow.com/a/13105359 if isinstance(input, dict): return {self.__byteify(key): self.__byteify(value) for key, value in input.iteritems()} elif isinstance(input, list): return [self.__byteify(element) for element in input] elif isinstance(input, unicode): return input.encode('utf-8') else: return input
from clearblade.ClearBladeCore import System, Query, Developer, registerDev import urllib.request, json, time ## New system with ClearBlade key and secret systemKey = "SYSTEMKEY_HERE" systemSecret = "SYSTEMSECRET_HERE" mySystem = System(systemKey, systemSecret) ## New device with Clearblade active key and name deviceName = "DEVICENAME_HERE" deviceActiveKey = "ACTIVEKEY_HERE" macDevice = mySystem.Device(deviceName, deviceActiveKey) token = macDevice.token ## Using device to access messaging client mqtt = mySystem.Messaging(macDevice, port=1883) subscribeTopic = "rohith-mac/1/requests" def on_connect(client, userdata, flags, rc): global subscribeTopic client.subscribe(subscribeTopic) incomingRequest = None def on_message(client, userdata, msg): global incomingRequest incomingRequest = (msg.payload).decode('utf-8') mqtt.on_connect = on_connect mqtt.on_message = on_message
help='Adapter Device Key') parser.add_argument('-tp', '--topic', action='store', type=str, default="device/ble/", help='Adapter Device Key') parser.add_argument('-sc', '--schematable', action='store', type=str, default="dev_admin_devicetypes", help='Device Schema Collection') parser.add_argument('-dw', '--devicewhitelist', action='store', type=str, default="dev_whitelist", help='Device Whitelist Collection') arg = parser.parse_args(sys.argv[1:]) TOPIC=arg.topic logger = setup_custom_logger('BLE Adapter') scanner=ScanDelegate() exitapp=False cbSystem=System(arg.systemkey, arg.systemsecret, arg.systemurl) # cbAuth=cbSystem.User(CBUSER, CBPASS) cbAuth=cbSystem.Device(arg.adaptername, arg.adapterkey) mqtt=cbSystem.Messaging(cbAuth) mqtt.connect() #Connect to the msg broker while not exitapp: dev={} #List of devices to schema and devices monitor whitelisttable = cbSystem.Collection(cbAuth, collectionName=arg.devicewhitelist) wl_rows = whitelisttable.getItems() schematable = cbSystem.Collection(cbAuth, collectionName=arg.schematable) schema_rows = schematable.getItems() for row in schema_rows: SC[row["item_id"]]=row["schema"] for row in wl_rows: WL[row["device_id"]]=SC[row["devicetype"]] #if "00:0b:57:1a:8f:de" in wl:
logging.debug("Setting cbLogs.MQTT_DEBUG to False") cbLogs.MQTT_DEBUG = False logging.info("Intializing ClearBlade device client") logging.debug("System Key = %s", CB_CONFIG['systemKey']) logging.debug("System Secret = %s", CB_CONFIG['systemSecret']) logging.debug("HTTP URL = %s", CB_CONFIG['httpURL'] + ":" + CB_CONFIG['httpPort']) CB_SYSTEM = System(CB_CONFIG['systemKey'], CB_CONFIG['systemSecret'], CB_CONFIG['httpURL'] + \ ":" + CB_CONFIG['httpPort']) logging.info("Authenticating to ClearBlade") logging.debug("Device ID = %s", CB_CONFIG['deviceID']) logging.debug("Device Active Key = %s", CB_CONFIG['activeKey']) CB_AUTH = CB_SYSTEM.Device(CB_CONFIG['deviceID'], CB_CONFIG['activeKey']) #Retrieve the adapter configuration if CB_CONFIG['adapterSettingsCollectionName'] != "": logging.info("Retrieving the adapter configuration settings") get_adapter_config() ######################### #BEGIN MQTT SPECIFIC CODE ######################### #Connect to the message broker # logging.info("Initializing the ClearBlade message broker") # CB_MQTT = CB_SYSTEM.Messaging(CB_AUTH) # CB_MQTT.on_log = on_log
def run_async_server(): """ The main loop instantiates one or more PyModbus servers mapped to ClearBlade Modbus proxies based on IP address and port defined in a ClearBlade platform Collection """ log = None virtual_ifs = [] err_msg = None defer_reactor = False try: parser = get_parser() user_options = parser.parse_args() local_ip_address = user_options.ip_address local_tcp_port = user_options.tcp_port net_if = user_options.net_if if user_options.log_level == 'DEBUG': _debug = True else: _debug = False HEARTBEAT = user_options.heartbeat log = headless.get_wrapping_logger(name=ADAPTER_DEVICE_ID, debug=_debug) server_log = headless.get_wrapping_logger(name="pymodbus.server", debug=_debug) log.info("Initializing ClearBlade System connection") cb_system = System(systemKey=user_options.systemKey, systemSecret=user_options.systemSecret, url=user_options.url) cb_auth = cb_system.Device(name=user_options.deviceName, key=user_options.deviceKey) cb_slave_config = user_options.slaves_collection cb_data = user_options.data_collection ip_proxies = [] proxy_ports = [] ip_address = None collection = cb_system.Collection(cb_auth, collectionName=cb_slave_config) query = Query() query.notEqualTo(COL_PROXY_IP_ADDRESS, '') rows = collection.getItems(query) for row in rows: # TODO: allow for possibility of multiple IPs with same port or same IP with multiple ports ip_address = str(row[COL_PROXY_IP_ADDRESS]) tcp_port = int(row[COL_PROXY_IP_PORT]) if ip_address not in ip_proxies: log.info("Found slave at {} on ClearBlade adapter config".format(ip_address)) ip_proxies.append(ip_address) proxy_ports.append(tcp_port) else: log.warning("Duplicate proxy IP address {} found in configuration - ignoring".format(ip_address)) log.debug("Processing {} slaves".format(len(ip_proxies))) for i in range(0, len(ip_proxies)): log.debug("Getting server context for {}".format(ip_proxies[i])) context = ClearBladeModbusProxyServerContext(cb_system=cb_system, cb_auth=cb_auth, cb_slaves_config=cb_slave_config, cb_data=cb_data, ip_address=ip_proxies[i], log=log) # Create IP aliases local_ip_address = ip_proxies[i] ip_mask = '255.255.255.0' local_tcp_port = proxy_ports[i] if sys.platform.startswith('win'): log.info("I'm on Windows!") local_ip_address = 'localhost' elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): virtual_if = '{nif}:{alias}'.format(nif=net_if, alias=i) virtual_ifs.append(virtual_if) linux_command = "ifconfig {vif} {ip}".format(vif=virtual_if, ip=local_ip_address) if ip_mask is not None: linux_command += " netmask {mask}".format(mask=ip_mask) log.info("Creating virtual IP address / alias via $ {}".format(linux_command)) subprocess.call(linux_command, shell=True) # Create Server Identification identity = ModbusDeviceIdentification() identity.VendorName = 'PyModbus' identity.VendorUrl = 'http://github.com/bashwork/pymodbus/' identity.ProductName = 'Inmarsat/ClearBlade Modbus Server Adapter' identity.ModelName = ip_proxies[i] identity.MajorMinorRevision = '1.0' # Setup Modbus TCP Server log.info("Starting Modbus TCP server on {}:{}".format(local_ip_address, local_tcp_port)) modbus_server_args = { 'context': context, 'identity': identity, 'address': (local_ip_address, local_tcp_port), # 'console': _debug, 'defer_reactor_run': True, } if modbus_server_args['defer_reactor_run']: defer_reactor = True reactor.callInThread(StartTcpServer, **modbus_server_args) if local_ip_address == 'localhost': log.info("Windows retricted environment prevents IP alias - running localhost for {}" .format(ip_proxies[i])) break reactor.callInThread(_heartbeat, log, time.time(), HEARTBEAT) if defer_reactor: reactor.suggestThreadPoolSize(len(ip_proxies)) reactor.run() except KeyboardInterrupt: err_msg = "modbus_server_adapter.py halted by Keyboard Interrupt" if log is not None: log.info(err_msg) else: print(err_msg) sys.exit("modbus_server_adapter.py halted by Keyboard Interrupt") except Exception as e: err_msg = "EXCEPTION: {}".format(e) if log is not None: log.info(err_msg) else: print(err_msg) sys.exit("modbus_server_adapter.py halted by exception {}".format(e)) finally: if defer_reactor and reactor.running: reactor.stop() for vif in virtual_ifs: debug_msg = "Taking down virtual interface {}".format(vif) if log is not None: log.debug(debug_msg) else: print(debug_msg) linux_command = "ifconfig {} down".format(vif) subprocess.call(linux_command, shell=True) print("Exiting...")