diff --git a/operations/c8y_Coils b/operations/c8y_Coils index 8b12000..9fe5c95 100644 --- a/operations/c8y_Coils +++ b/operations/c8y_Coils @@ -1,4 +1,4 @@ [exec] - topic = "c8y/s/ds" - on_message = "xy" + topic = "c8y/devicecontrol/notifications" + on_fragment = "c8y_Coils" command = "python3 -m tedge_modbus.operations c8y_Coils" diff --git a/operations/c8y_ModbusConfiguration b/operations/c8y_ModbusConfiguration index f4775fd..bee407f 100644 --- a/operations/c8y_ModbusConfiguration +++ b/operations/c8y_ModbusConfiguration @@ -1,4 +1,4 @@ [exec] - topic = "c8y/s/dc/modbus" - on_message = "1" - command = "python3 -m tedge_modbus.operations c8y_ModbusConfiguration" \ No newline at end of file + topic = "c8y/devicecontrol/notifications" + on_fragment = "c8y_ModbusConfiguration" + command = "python3 -m tedge_modbus.operations c8y_ModbusConfiguration ${.payload.c8y_ModbusConfiguration}" diff --git a/operations/c8y_ModbusDevice b/operations/c8y_ModbusDevice index e35d244..e549fad 100644 --- a/operations/c8y_ModbusDevice +++ b/operations/c8y_ModbusDevice @@ -1,4 +1,4 @@ [exec] - topic = "c8y/s/dc/modbus" - on_message = "2" - command = "python3 -m tedge_modbus.operations c8y_ModbusDevice" + topic = "c8y/devicecontrol/notifications" + on_fragment = "c8y_ModbusDevice" + command = "python3 -m tedge_modbus.operations c8y_ModbusDevice ${.payload.c8y_ModbusDevice}" diff --git a/operations/c8y_Registers b/operations/c8y_Registers index b053fdc..57a052e 100644 --- a/operations/c8y_Registers +++ b/operations/c8y_Registers @@ -1,4 +1,4 @@ [exec] - topic = "c8y/s/ds" - on_message = "xy" + topic = "c8y/devicecontrol/notifications" + on_fragment = "c8y_Registers" command = "python3 -m tedge_modbus.operations c8y_Registers" diff --git a/operations/c8y_SerialConfiguration b/operations/c8y_SerialConfiguration index ae2e717..8e46e4f 100644 --- a/operations/c8y_SerialConfiguration +++ b/operations/c8y_SerialConfiguration @@ -1,4 +1,4 @@ [exec] - topic = "c8y/s/dc/modbus" - on_message = "3" - command = "python3 -m tedge_modbus.operations c8y_SerialConfiguration" \ No newline at end of file + topic = "c8y/devicecontrol/notifications" + on_fragment = "c8y_SerialConfiguration" + command = "python3 -m tedge_modbus.operations c8y_SerialConfiguration ${.payload.c8y_SerialConfiguration}" diff --git a/scripts/deb/postinst b/scripts/deb/postinst index d2fd34f..3ddb3d8 100644 --- a/scripts/deb/postinst +++ b/scripts/deb/postinst @@ -1,7 +1,6 @@ #!/bin/sh set -e -tedge config add c8y.smartrest.templates modbus tedge refresh-bridges # Automatically added by thin-edge.io diff --git a/scripts/rpm/postinst b/scripts/rpm/postinst index 0f50164..c99faf2 100644 --- a/scripts/rpm/postinst +++ b/scripts/rpm/postinst @@ -1,7 +1,6 @@ #!/bin/sh set -e -tedge config add c8y.smartrest.templates modbus tedge refresh-bridges # Automatically added by thin-edge.io diff --git a/tedge_modbus/operations/__main__.py b/tedge_modbus/operations/__main__.py index 2847690..aaf40f9 100644 --- a/tedge_modbus/operations/__main__.py +++ b/tedge_modbus/operations/__main__.py @@ -24,7 +24,7 @@ def main(): elif command == "c8y_SerialConfiguration": run = c8y_serial_configuration.run - arguments = sys.argv[2].split(",") if len(sys.argv) > 2 else [] + arguments = sys.argv[2:] context = Context() run(arguments, context) diff --git a/tedge_modbus/operations/c8y_modbus_configuration.py b/tedge_modbus/operations/c8y_modbus_configuration.py index 42beca6..900b1f7 100644 --- a/tedge_modbus/operations/c8y_modbus_configuration.py +++ b/tedge_modbus/operations/c8y_modbus_configuration.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Cumulocity IoT ModbusConfiguration operation handler""" +"""Cumulocity ModbusConfiguration operation handler""" import json import logging import toml @@ -15,18 +15,17 @@ def run(arguments, context: Context): """Run c8y_ModbusConfiguration operation handler""" - if len(arguments) != 4: - raise ValueError( - f"Expected 4 arguments in smart rest template. Got {len(arguments)}" - ) + if len(arguments) != 1: + raise ValueError(f"Expected 1 argument. Got {len(arguments)}") # Get device configuration modbus_config = context.base_config loglevel = modbus_config["modbus"]["loglevel"] or "INFO" logger.setLevel(getattr(logging, loglevel.upper(), logging.INFO)) logger.info("New c8y_ModbusConfiguration operation") logger.debug("Current configuration: %s", modbus_config) - transmit_rate = int(arguments[2]) - polling_rate = int(arguments[3]) + data = json.loads(arguments[0]) + transmit_rate = data["transmitRate"] + polling_rate = data["pollingRate"] logger.debug("transmitRate: %d, pollingRate: %d", transmit_rate, polling_rate) # Update configuration diff --git a/tedge_modbus/operations/c8y_modbus_device.py b/tedge_modbus/operations/c8y_modbus_device.py index c7d9fd4..bca503f 100644 --- a/tedge_modbus/operations/c8y_modbus_device.py +++ b/tedge_modbus/operations/c8y_modbus_device.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 -"""Cumulocity IoT Modbus device operation handler""" +"""Cumulocity Modbus device operation handler""" import logging from dataclasses import dataclass +import json import requests import toml @@ -76,13 +77,14 @@ def get_device_from_mapping(target: ModebusDevice, mapping): def parse_arguments(arguments) -> ModebusDevice: """Parse operation arguments""" + data = json.loads(arguments[0]) return ModebusDevice( - modbus_type=arguments[2], # Only works for TCP. - modbus_address=arguments[3], - child_name=arguments[4], - modbus_server=arguments[5], - device_id=arguments[6], - mapping_path=arguments[7], + modbus_type=data["protocol"], + modbus_address=data["address"], + child_name=data["name"], + modbus_server=data["ipAddress"], + device_id=data["id"], + mapping_path=data["type"], ) @@ -92,12 +94,8 @@ def run(arguments, context: Context): logger.setLevel(getattr(logging, loglevel.upper(), logging.INFO)) logger.info("New c8y_ModbusDevice operation") # Check and store arguments - if len(arguments) != 8: - raise ValueError( - "Expected 8 arguments in smart rest template. Got " - + str(len(arguments)) - + "." - ) + if len(arguments) != 1: + raise ValueError("Expected 1 argument. Got " + str(len(arguments)) + ".") config_path = context.config_dir / "devices.toml" target = parse_arguments(arguments) diff --git a/tedge_modbus/operations/c8y_serial_configuration.py b/tedge_modbus/operations/c8y_serial_configuration.py index d71ed84..0f94ced 100644 --- a/tedge_modbus/operations/c8y_serial_configuration.py +++ b/tedge_modbus/operations/c8y_serial_configuration.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Cumulocity IoT SerialConfiguration operation handler""" +"""Cumulocity SerialConfiguration operation handler""" import json import logging import toml @@ -13,22 +13,22 @@ ) +# pylint: disable=duplicate-code def run(arguments, context: Context): """Run c8y_SerialConfiguration operation handler""" - if len(arguments) != 6: - raise ValueError( - f"Expected 6 arguments in smart rest template. Got {len(arguments)}" - ) + if len(arguments) != 1: + raise ValueError(f"Expected 1 argument. Got {len(arguments)}") # Get device configuration modbus_config = context.base_config loglevel = modbus_config["modbus"]["loglevel"] or "INFO" logger.setLevel(getattr(logging, loglevel.upper(), logging.INFO)) logger.info("New c8y_SerialConfiguration operation") logger.debug("Current configuration: %s", modbus_config) - baud_rate = int(arguments[2]) - stop_bits = int(arguments[3]) - parity = arguments[4] - data_bits = int(arguments[5]) + data = json.loads(arguments[0]) + baud_rate = data["baudRate"] + stop_bits = data["stopBits"] + parity = data["parity"] + data_bits = data["dataBits"] logger.debug( "baudRate: %d, stopBits: %d, parity: %s, dataBits: %d", baud_rate, diff --git a/tedge_modbus/reader/reader.py b/tedge_modbus/reader/reader.py index cd4b10a..2203c85 100644 --- a/tedge_modbus/reader/reader.py +++ b/tedge_modbus/reader/reader.py @@ -18,7 +18,6 @@ from .banner import BANNER from .mapper import MappedMessage, ModbusMapper -from .smartresttemplates import SMARTREST_TEMPLATES DEFAULT_FILE_DIR = "/etc/tedge/plugins/modbus" BASE_CONFIG_NAME = "modbus.toml" @@ -100,11 +99,10 @@ def reread_config(self): if self.tedge_client is not None and self.tedge_client.is_connected(): self.tedge_client.disconnect() self.tedge_client = self.connect_to_tedge() - # If connected to tedge, register service, update config and send smart rest template + # If connected to tedge, register service, update config time.sleep(5) self.register_child_devices(self.devices) self.register_service() - self.send_smartrest_templates() self.update_base_config_on_device(self.base_config) self.update_modbus_info_on_child_devices(self.devices) for evt in self.poll_scheduler.queue: @@ -409,13 +407,6 @@ def connect_to_tedge(self): self.logger.error("Failed to connect to thin-edge.io: %s", e) time.sleep(5) - def send_smartrest_templates(self): - """Publish the Cumulocity IoT SmartREST template which are related to fieldbus messages""" - self.logger.debug("Send smart rest templates to tedge broker") - topic = "c8y/s/ut/modbus" - template = "\n".join(str(template) for template in SMARTREST_TEMPLATES) - self.send_tedge_message(MappedMessage(template, topic)) - def update_base_config_on_device(self, base_config): """Update the base configuration""" self.logger.debug("Update base config on device") diff --git a/tedge_modbus/reader/smartresttemplates.py b/tedge_modbus/reader/smartresttemplates.py deleted file mode 100644 index 89e9ee0..0000000 --- a/tedge_modbus/reader/smartresttemplates.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Cumulocity IoT SmartREST template definitions""" - -# pylint: disable=line-too-long -SMARTREST_TEMPLATES = [ - "11,1,,c8y_ModbusConfiguration,c8y_ModbusConfiguration.transmitRate,c8y_ModbusConfiguration.pollingRate", - "11,2,,c8y_ModbusDevice,c8y_ModbusDevice.protocol,c8y_ModbusDevice.address,c8y_ModbusDevice.name,c8y_ModbusDevice.ipAddress,c8y_ModbusDevice.id,c8y_ModbusDevice.type", - "11,3,,c8y_SerialConfiguration,c8y_SerialConfiguration.baudRate,c8y_SerialConfiguration.stopBits,c8y_SerialConfiguration.parity,c8y_SerialConfiguration.dataBits", -] diff --git a/tests/c8y_ModbusConfiguration/operation.robot b/tests/c8y_ModbusConfiguration/operation.robot index aa8d88d..d003d1d 100644 --- a/tests/c8y_ModbusConfiguration/operation.robot +++ b/tests/c8y_ModbusConfiguration/operation.robot @@ -6,7 +6,7 @@ Suite Setup Set Main Device *** Variables *** -${EXPECTED_TRANSMIT_RATE} 3 +${EXPECTED_TRANSMIT_RATE} 6 ${EXPECTED_POLLING_RATE} 3 diff --git a/tests/c8y_SerialConfiguration/operation.robot b/tests/c8y_SerialConfiguration/operation.robot new file mode 100644 index 0000000..2b2a4f1 --- /dev/null +++ b/tests/c8y_SerialConfiguration/operation.robot @@ -0,0 +1,58 @@ +*** Settings *** +Resource ../resources/common.robot +Library Cumulocity + +Suite Setup Set Main Device + +*** Variables *** + +${EXPECTED_BAUD_RATE} 9600 +${EXPECTED_STOP_BITS} 2 +${EXPECTED_PARITY} N +${EXPECTED_DATA_BITS} 8 + + +*** Test Cases *** +Set values via c8y_SerialConfiguration Operation + ${operation}= Update Serial Configuration Settings + ... baud_rate=${EXPECTED_BAUD_RATE} + ... stop_bits=${EXPECTED_STOP_BITS} + ... parity=${EXPECTED_PARITY} + ... data_bits=${EXPECTED_DATA_BITS} + Cumulocity.Operation Should Be SUCCESSFUL ${operation} + +Serial configuration should be updated for the Device + ${mo}= Managed Object Should Have Fragment Values + ... c8y_SerialConfiguration.baudRate\=${EXPECTED_BAUD_RATE} + ... c8y_SerialConfiguration.stopBits\=${EXPECTED_STOP_BITS} + ... c8y_SerialConfiguration.parity\=${EXPECTED_PARITY} + ... c8y_SerialConfiguration.dataBits\=${EXPECTED_DATA_BITS} + + ${baudrate}= Set Variable ${mo}[c8y_SerialConfiguration][baudRate] + ${stopbits}= Set Variable ${mo}[c8y_SerialConfiguration][stopBits] + ${parity}= Set Variable ${mo}[c8y_SerialConfiguration][parity] + ${databits}= Set Variable ${mo}[c8y_SerialConfiguration][dataBits] + + Should Be Equal As Numbers ${baudrate} ${EXPECTED_BAUD_RATE} + Should Be Equal As Numbers ${stopbits} ${EXPECTED_STOP_BITS} + Should Be Equal As Strings ${parity} ${EXPECTED_PARITY} + Should Be Equal As Numbers ${databits} ${EXPECTED_DATA_BITS} + +Serial configuration should be updated on the Device + ${shell_operation}= Execute Shell Command cat /etc/tedge/plugins/modbus/modbus.toml + ${shell_operation}= Cumulocity.Operation Should Be SUCCESSFUL ${shell_operation} + + ${result_text}= Set Variable ${shell_operation}[c8y_Command][result] + + Should Contain ${result_text} baudrate = ${EXPECTED_BAUD_RATE} + Should Contain ${result_text} stopbits = ${EXPECTED_STOP_BITS} + Should Contain ${result_text} parity = "${EXPECTED_PARITY}" + Should Contain ${result_text} databits = ${EXPECTED_DATA_BITS} + +*** Keywords *** + +Update Serial Configuration Settings + [Arguments] ${baud_rate} ${stop_bits} ${parity} ${data_bits} + ${operation}= Cumulocity.Create Operation + ... fragments={"c8y_SerialConfiguration": {"baudRate":${baud_rate},"stopBits":${stop_bits},"parity":"${parity}","dataBits":${data_bits}}} + RETURN ${operation} diff --git a/tests/modbus_reader/debian.robot b/tests/modbus_reader/debian.robot index 000d306..deaa7bf 100644 --- a/tests/modbus_reader/debian.robot +++ b/tests/modbus_reader/debian.robot @@ -23,6 +23,7 @@ ReInstall Modbus Plugin Operation Should Be SUCCESSFUL ${uninstall_operation} timeout=60 Device Should Not Have Installed Software tedge-modbus-plugin + # Ensure smartrest config has no longer 'modbus' after uninstall ${templates}= Get tedge smartrest config Should Be Equal ${templates} [] msg=SmartREST Message should be removed @@ -44,9 +45,6 @@ ReInstall Modbus Plugin # Check if plugin is running System D Service should be Active tedge-modbus-plugin - ${templates}= Get tedge smartrest config - Should Be Equal ${templates} ["modbus"] msg=SmartREST Message should be removed - *** Keywords *** Get Debian Package Version