├── .github ├── CODEOWNERS └── pull_request_template.md ├── .gitignore ├── .gitmodules ├── Jenkinsfile ├── LICENSE ├── Makefile ├── README.md ├── config.sample.json ├── configs ├── config.json.default ├── config.json.wb234 ├── config.json.wb5 ├── config.json.wb6 ├── config.json.wb67 ├── config.json.wb7 ├── config.json.wb8 └── config.json.wb85 ├── debian ├── changelog ├── compat ├── control ├── copyright ├── rules ├── wb-mqtt-serial.dirs ├── wb-mqtt-serial.postinst ├── wb-mqtt-serial.postrm └── wb-mqtt-serial.wb-mqtt-serial.service ├── doc ├── timeouts.puml └── timeouts.svg ├── generate-system-config.sh ├── groups.json ├── obis-hints.json ├── protocols ├── dlms.schema.json ├── energomera-c.schema.json ├── energomera.schema.json ├── iec-c.schema.json ├── ivtm.schema.json ├── lls.schema.json ├── mercury200.schema.json ├── mercury230.schema.json ├── milur.schema.json ├── modbus-io.schema.json ├── modbus.schema.json ├── neva.schema.json ├── pulsar.schema.json ├── s2k.schema.json └── uniel.schema.json ├── src ├── bcd_utils.cpp ├── bcd_utils.h ├── bin_utils.cpp ├── bin_utils.h ├── common_utils.cpp ├── common_utils.h ├── confed_channel_modes.cpp ├── confed_channel_modes.h ├── confed_config_generator.cpp ├── confed_config_generator.h ├── confed_config_generator_with_groups.cpp ├── confed_config_generator_with_groups.h ├── confed_device_schemas_map.cpp ├── confed_device_schemas_map.h ├── confed_json_generator.cpp ├── confed_json_generator.h ├── confed_json_generator_with_groups.cpp ├── confed_json_generator_with_groups.h ├── confed_protocol_schemas_map.cpp ├── confed_protocol_schemas_map.h ├── confed_schema_generator.cpp ├── confed_schema_generator.h ├── confed_schema_generator_with_groups.cpp ├── confed_schema_generator_with_groups.h ├── config_merge_template.cpp ├── config_merge_template.h ├── config_schema_generator.cpp ├── config_schema_generator.h ├── crc16.cpp ├── crc16.h ├── definitions.h ├── device_template_generator.cpp ├── device_template_generator.h ├── devices │ ├── curtains │ │ ├── a_ok_device.cpp │ │ ├── a_ok_device.h │ │ ├── dooya_device.cpp │ │ ├── dooya_device.h │ │ ├── somfy_sdn_device.cpp │ │ ├── somfy_sdn_device.h │ │ ├── windeco_device.cpp │ │ └── windeco_device.h │ ├── dlms_device.cpp │ ├── dlms_device.h │ ├── em_device.cpp │ ├── em_device.h │ ├── energomera_ce_device.cpp │ ├── energomera_ce_device.h │ ├── energomera_iec_device.cpp │ ├── energomera_iec_device.h │ ├── energomera_iec_mode_c_device.cpp │ ├── energomera_iec_mode_c_device.h │ ├── iec_mode_c_device.cpp │ ├── iec_mode_c_device.h │ ├── ivtm_device.cpp │ ├── ivtm_device.h │ ├── lls_device.cpp │ ├── lls_device.h │ ├── mercury200_device.cpp │ ├── mercury200_device.h │ ├── mercury230_device.cpp │ ├── mercury230_device.h │ ├── milur_device.cpp │ ├── milur_device.h │ ├── modbus_device.cpp │ ├── modbus_device.h │ ├── modbus_io_device.cpp │ ├── modbus_io_device.h │ ├── neva_device.cpp │ ├── neva_device.h │ ├── pulsar_device.cpp │ ├── pulsar_device.h │ ├── s2k_device.cpp │ ├── s2k_device.h │ ├── uniel_device.cpp │ └── uniel_device.h ├── expression_evaluator.cpp ├── expression_evaluator.h ├── file_utils.cpp ├── file_utils.h ├── files_watcher.cpp ├── files_watcher.h ├── iec_common.cpp ├── iec_common.h ├── json_common.cpp ├── json_common.h ├── log.cpp ├── log.h ├── main.cpp ├── modbus_base.cpp ├── modbus_base.h ├── modbus_common.cpp ├── modbus_common.h ├── modbus_ext_common.cpp ├── modbus_ext_common.h ├── poll_plan.h ├── pollable_device.cpp ├── pollable_device.h ├── port │ ├── feature_port.cpp │ ├── feature_port.h │ ├── file_descriptor_port.cpp │ ├── file_descriptor_port.h │ ├── port.cpp │ ├── port.h │ ├── serial_port.cpp │ ├── serial_port.h │ ├── serial_port_settings.h │ ├── tcp_port.cpp │ ├── tcp_port.h │ └── tcp_port_settings.h ├── register.cpp ├── register.h ├── register_handler.cpp ├── register_handler.h ├── register_value.cpp ├── register_value.h ├── rpc │ ├── rpc_config.cpp │ ├── rpc_config.h │ ├── rpc_config_handler.cpp │ ├── rpc_config_handler.h │ ├── rpc_device_handler.cpp │ ├── rpc_device_handler.h │ ├── rpc_device_load_config_task.cpp │ ├── rpc_device_load_config_task.h │ ├── rpc_device_load_task.cpp │ ├── rpc_device_load_task.h │ ├── rpc_device_probe_task.cpp │ ├── rpc_device_probe_task.h │ ├── rpc_device_set_task.cpp │ ├── rpc_device_set_task.h │ ├── rpc_exception.cpp │ ├── rpc_exception.h │ ├── rpc_helpers.cpp │ ├── rpc_helpers.h │ ├── rpc_port_driver_list.cpp │ ├── rpc_port_driver_list.h │ ├── rpc_port_handler.cpp │ ├── rpc_port_handler.h │ ├── rpc_port_load_modbus_serial_client_task.cpp │ ├── rpc_port_load_modbus_serial_client_task.h │ ├── rpc_port_load_raw_serial_client_task.cpp │ ├── rpc_port_load_raw_serial_client_task.h │ ├── rpc_port_load_request.cpp │ ├── rpc_port_load_request.h │ ├── rpc_port_scan_serial_client_task.cpp │ ├── rpc_port_scan_serial_client_task.h │ ├── rpc_port_setup_serial_client_task.cpp │ └── rpc_port_setup_serial_client_task.h ├── running_average.h ├── serial_client.cpp ├── serial_client.h ├── serial_client_device_access_handler.cpp ├── serial_client_device_access_handler.h ├── serial_client_events_reader.cpp ├── serial_client_events_reader.h ├── serial_client_register_poller.cpp ├── serial_client_register_poller.h ├── serial_config.cpp ├── serial_config.h ├── serial_device.cpp ├── serial_device.h ├── serial_driver.cpp ├── serial_driver.h ├── serial_exc.cpp ├── serial_exc.h ├── serial_port_driver.cpp ├── serial_port_driver.h ├── templates_map.cpp ├── templates_map.h ├── wb_registers.cpp ├── wb_registers.h ├── write_channel_serial_client_task.cpp └── write_channel_serial_client_task.h ├── templates ├── config-akko.json ├── config-aok-am35.json ├── config-aok-am68-lm100.json ├── config-apc-nmc2.json ├── config-arlight-dali-logic-lite-ps-x1.json.jinja ├── config-bac-002aln.json ├── config-bac-6000-series.json ├── config-bac-6000aln.json ├── config-bac-6000elnw.json ├── config-bht-006-series.json ├── config-bht-6000-series.json ├── config-breezart-lux.json.jinja ├── config-carel-mu-rack.json ├── config-carel-pj-basic-deprecated.json ├── config-carel-pj-basic.json ├── config-carel-pj-easy.json ├── config-cityron-pu-3.json.jinja ├── config-danfoss-ekc-202b-deprecated.json ├── config-danfoss-ekc-202b-wb-ref-deprecated.json ├── config-danfoss-ekc-202b-wb-ref.json ├── config-danfoss-ekc-202b.json ├── config-danfoss-ekc-202d-deprecated.json ├── config-danfoss-ekc-202d-wb-ref-deprecated.json ├── config-danfoss-ekc-202d-wb-ref.json ├── config-danfoss-ekc-202d.json ├── config-danfoss-ekc-204a1-deprecated.json ├── config-danfoss-ekc-204a1-wb-ref-deprecated.json ├── config-danfoss-ekc-204a1-wb-ref.json ├── config-danfoss-ekc-204a1.json ├── config-danfoss-erc-211-wb-ref.json ├── config-danfoss-erc-213-wb-ref.json ├── config-danfoss-erc-214-wb-ref.json ├── config-danfoss-fc51.json ├── config-dauerhaft-35-45.json ├── config-dauerhaft-cm5.json ├── config-dauerhaft-deprecated.json ├── config-ddl04r.json ├── config-ddl24.json ├── config-ddm845r.json.jinja ├── config-dooya-dm35eq-x.json ├── config-dooya82.json ├── config-drb88.json ├── config-ecodim-dali-gw2.json.jinja ├── config-eliwell-id-974-lx-wb-ref.json ├── config-eliwell-id-985-lx-wb-ref.json ├── config-eliwell-idplus-9xx-wb-ref.json ├── config-eliwell-idplus-9xx.json ├── config-energomera-ce102.json ├── config-energomera-ce102m.json ├── config-energomera-ce301.json ├── config-energomera-ce303.json ├── config-energomera-ce308.json ├── config-ensystec.json.jinja ├── config-escort-db-2.json ├── config-haier-ycj-a002.json ├── config-ivtm-7m-3.json ├── config-kaplestop.json.jinja ├── config-komfovent.json ├── config-kvadro-1wire.json ├── config-lc103.json ├── config-luna.json ├── config-map12e-fw2.json.jinja ├── config-map12h-all-harmonics.json ├── config-map12h-basic-div2.json ├── config-map12h-basic.json ├── config-map12h-fw2-all-harmonics.json ├── config-map12h-fw2-basic.json ├── config-map12h-fw2-harmonics.json ├── config-map12h-fw2.json ├── config-map12h-harmonics.json ├── config-map12h.json ├── config-map3e-fw2.json ├── config-map3e.json ├── config-map3et.json ├── config-map3ev.json ├── config-map3h-basic.json ├── config-map3h-fw2-basic.json ├── config-map3h-fw2-harmonics.json ├── config-map3h-fw2.json ├── config-map3h-harmonics.json ├── config-map3h.json ├── config-map6s-fw2.json ├── config-map6s.json ├── config-meanwell-drs.json ├── config-mercury200_02.json ├── config-mercury230.json ├── config-mercury234.json ├── config-milur-105.json ├── config-milur-305.json ├── config-mst-24.json ├── config-msu21.json ├── config-msu24.json ├── config-msu34.json ├── config-msu34tlhp.json ├── config-mtdx62-mb.json ├── config-neva-mt124.json ├── config-neva-mt32x.json ├── config-oni-plc-w-acs-0800-imp.json.jinja ├── config-oni-plc-w-ema-0304.json.jinja ├── config-oni-plc-w-ema-06u00.json.jinja ├── config-oni-plc-w-emd-0706.json.jinja ├── config-onokom-air-aux-1-mb-b.json ├── config-onokom-air-cg-vrf-mb-b.json ├── config-onokom-air-dk-1-mb-b.json ├── config-onokom-air-dk-5-mb-b.json ├── config-onokom-air-gr-1-mb-b.json ├── config-onokom-air-gr-3-mb-b.json ├── config-onokom-air-gr-p3-mb-b.json ├── config-onokom-air-hr-1-mb-b.json ├── config-onokom-air-hs-3-mb-b.json ├── config-onokom-air-hs-5-mb-b.json ├── config-onokom-air-hs-6-mb-b.json ├── config-onokom-air-ht-1-mb-b.json ├── config-onokom-air-md-1-mb-b.json ├── config-onokom-air-md-3-mb-b.json ├── config-onokom-air-md-vrf-mb-b.json ├── config-onokom-air-me-1-mb-b.json ├── config-onokom-air-mh-2-mb-b.json ├── config-onokom-air-tcl-1-mb-b.json ├── config-onokom-air-tcl-3-mb-b.json ├── config-onokom-air-tcl-6-mb-b.json ├── config-pd561z.json ├── config-ptex.json ├── config-pulsar-heat.json ├── config-pulsar-m-water.json ├── config-pulsar-water.json ├── config-pzem-016.json ├── config-ridan-greencon-r.json ├── config-s2k-sp1.json ├── config-sdm120.json ├── config-sdm220.json ├── config-siemens-rdf302.json ├── config-sokol-m.json ├── config-somfy-sdn-deprecated.json ├── config-somfy-sdn.json ├── config-somfy-transmitter.json ├── config-t13-frequency-v2.json ├── config-t13-frequency.json ├── config-teplomash-kev-blok-mk.json ├── config-tm-p3r3.json ├── config-uniel-uch-m111rx.json.jinja ├── config-uniel-uch-m121rx.json ├── config-uniel-uch-m141rc.json ├── config-vacon10.json ├── config-vakio-city-air-250-500.json ├── config-veda-vf51.json ├── config-wb-domofon-mb.json ├── config-wb-led.json.jinja ├── config-wb-m1w2-buttons.json.jinja ├── config-wb-m1w2-di.json ├── config-wb-m1w2.json ├── config-wb-mai11-deprecated.json ├── config-wb-mai11.json.jinja ├── config-wb-mai2-cc.json ├── config-wb-mai6.json.jinja ├── config-wb-mao4-20ma.json.jinja ├── config-wb-mao4-deprecated.json.jinja ├── config-wb-mao4.json.jinja ├── config-wb-mcm16.json ├── config-wb-mcm8.json.jinja ├── config-wb-mdm2.json ├── config-wb-mdm3-deprecated.json.jinja ├── config-wb-mdm3.json.jinja ├── config-wb-mir.json ├── config-wb-mir_simple.json ├── config-wb-mir_v2.json ├── config-wb-mir_v2_buttons.json.jinja ├── config-wb-mir_v3.json.jinja ├── config-wb-mr11.json ├── config-wb-mr14.json ├── config-wb-mr3.json.jinja ├── config-wb-mr3lv.json ├── config-wb-mr6c-nc.json.jinja ├── config-wb-mr6c.json.jinja ├── config-wb-mr6cu.json.jinja ├── config-wb-mr6cv3.json.jinja ├── config-wb-mr6lv.json ├── config-wb-mrgb.json ├── config-wb-mrgbw-d-deprecated.json ├── config-wb-mrgbw-d-fw3-deprecated.json ├── config-wb-mrgbw-d-fw3.json.jinja ├── config-wb-mrgbw-d.json ├── config-wb-mrm2-mini-deprecated.json ├── config-wb-mrm2-mini-nc-deprecated.json ├── config-wb-mrm2-mini-nc.json.jinja ├── config-wb-mrm2-mini.json.jinja ├── config-wb-mrm2-old.json ├── config-wb-mrm2.json ├── config-wb-mrps6.json ├── config-wb-mrwm2.json.jinja ├── config-wb-ms-thls-v2.json ├── config-wb-ms-thls.json ├── config-wb-ms_v2-deprecated.json ├── config-wb-ms_v2.json ├── config-wb-msgr.json ├── config-wb-msw2.json ├── config-wb-msw_v3.json ├── config-wb-msw_v4.json ├── config-wb-msw_v4_lora.json ├── config-wb-mwac.json.jinja ├── config-wb-mwac2.json.jinja ├── config-wb-mwac2_ver2.json.jinja ├── config-wb-ups-v3.json.jinja ├── config-wbe2-i-ebus-deprecated.json ├── config-wbe2-i-ebus.json ├── config-wbe2-i-opentherm-fw1.3-deprecated.json ├── config-wbe2-i-opentherm-fw1.3.json ├── config-wbe2-i-opentherm-fw1.4-deprecated.json ├── config-wbe2-i-opentherm-fw1.4.json ├── config-wbe2-i-opentherm-fw1.7.3.json ├── config-wbio-ai-dv-12-20ma.json ├── config-wbio-ai-dv-12-50V.json ├── config-wbio-ai-dv-12.json ├── config-wbio-di-dr-14.json ├── config-wbio-di-dr-16.json ├── config-wbio-di-dr-8.json ├── config-wbio-di-hvd-16.json ├── config-wbio-di-hvd-8.json ├── config-wbio-di-wd-14.json ├── config-wbio-dio-ttl-8.json ├── config-wbio-do-hs-8.json ├── config-wbio-do-r10a-8.json ├── config-wbio-do-r10r-4.json ├── config-wbio-do-r1g-16.json ├── config-wbio-do-ssr-8.json ├── config-windeco.json ├── config-wp3066adam.json ├── config-wp8026adam.json ├── config-wp8027adam.json ├── config-wp8028adam.json ├── config-wp9038adam.json └── config-xy-md0x.json ├── test ├── TConfigParserTest.ParametersAsArray.dat ├── TConfigParserTest.Parse.dat ├── TConfigParserTest.ParseRateLimit.dat ├── TConfigParserTest.SameSetupItems.dat ├── TConfigParserTest.SetupCondition.dat ├── TConfigParserTest.UnsuccessfulParse.dat ├── TDeviceTemplatesTest.Validate.dat ├── TDlmsIntegrationTest.Poll.dat ├── TEMCustomPasswordTest.Combined.dat ├── TEMDeviceTest.Combined.dat ├── TEMDeviceTest.Mercury200Energy.dat ├── TEMDeviceTest.Mercury200Params.dat ├── TEMDeviceTest.Mercury230Exception.dat ├── TEMDeviceTest.Mercury230ReadEnergy.dat ├── TEMDeviceTest.Mercury230ReadParams.dat ├── TEMDeviceTest.Mercury230Reconnect.dat ├── TEMDeviceTest.MilurException.dat ├── TEMDeviceTest.MilurQuery.dat ├── TEMDeviceTest.MilurReconnect.dat ├── TEMIntegrationTest.Poll.dat ├── TEnergomeraCe102MIntegrationTest.Poll.dat ├── TEnergomeraIntegrationTest.Poll.dat ├── TExpressionsTest.Ast.dat ├── TExpressionsTest.ParsingError.dat ├── TIVTMDeviceTest.IVTM7MQuery.dat ├── TLLSIntegrationTest.Poll.dat ├── TMercury200IntegrationTest.Poll.dat ├── TMercury200Test.BatteryVoltageQuery.dat ├── TMercury200Test.EnergyQuery.dat ├── TMercury200Test.ParamsQuery.dat ├── TMercury230CustomPasswordTest.Test.dat ├── TMercury230IntegrationTest.Poll.dat ├── TMercury230Test.Exception.dat ├── TMercury230Test.ReadEnergy.dat ├── TMercury230Test.ReadParams.dat ├── TMercury230Test.Reconnect.dat ├── TMilur32Test.MilurQuery.dat ├── TMilurCustomPasswordTest.Test.dat ├── TMilurIntegrationTest.Poll.dat ├── TMilurTest.Exception.dat ├── TMilurTest.Query.dat ├── TMilurTest.Reconnect.dat ├── TModbusBitmasksIntegrationTest.Poll.dat ├── TModbusBitmasksIntegrationTest.SingleWrite.dat ├── TModbusBitmasksU32IntegrationTest.Poll.dat ├── TModbusBitmasksU32IntegrationTest.Write.dat ├── TModbusContinuousRegisterReadTest.NotSupported.dat ├── TModbusContinuousRegisterReadTest.Supported.dat ├── TModbusContinuousRegisterWriteTest.SetupItems.dat ├── TModbusIOIntegrationTest.Poll.dat ├── TModbusIOIntegrationTest.SetupErrors.dat ├── TModbusIOIntegrationTest.Write.dat ├── TModbusIntegrationTest.Errors.dat ├── TModbusIntegrationTest.GuardInterval.dat ├── TModbusIntegrationTest.Holes.dat ├── TModbusIntegrationTest.HolesAutoDisable.dat ├── TModbusIntegrationTest.MaxReadRegisters.dat ├── TModbusIntegrationTest.Poll.dat ├── TModbusIntegrationTest.Write.dat ├── TModbusLittleEndianRegisterTest.Read.dat ├── TModbusLittleEndianRegisterTest.Write.dat ├── TModbusPartialRegisterWriteTest.SetupItems.dat ├── TModbusPublishTest.DuplicateValues.dat ├── TModbusReconnectTest.Disconnect.dat ├── TModbusSeveralBitmasksIntegrationTest.Poll.dat ├── TModbusTest.CRCError.dat ├── TModbusTest.Errors.dat ├── TModbusTest.HoldingSingleMulti.dat ├── TModbusTest.MinReadRegisters.dat ├── TModbusTest.Query.dat ├── TModbusTest.ReadHoldingRegiterWithOffsetWriteOptions.dat ├── TModbusTest.ReadHoldingRegiterWithWriteAddress.dat ├── TModbusTest.ReadString.dat ├── TModbusTest.ReadString8.dat ├── TModbusTest.SkipNoiseAtPacketEnd.dat ├── TModbusTest.WriteHoldingRegiterWithOffsetWriteOptions.dat ├── TModbusTest.WriteHoldingRegiterWithWriteAddress.dat ├── TModbusTest.WriteOnlyHoldingRegiter.dat ├── TModbusTest.WriteOnlyHoldingRegiterNeg.dat ├── TModbusTest.WriteOnlyRegisters.dat ├── TModbusTest.WriteString.dat ├── TModbusTest.WriteString8.dat ├── TModbusTest.WrongFunctionCode.dat ├── TModbusTest.WrongFunctionCodeWithException.dat ├── TModbusTest.WrongFunctionCodeWithExceptionWrite.dat ├── TModbusTest.WrongFunctionCodeWrite.dat ├── TModbusTest.WrongResponseDataSize.dat ├── TModbusTest.WrongSlaveId.dat ├── TModbusTest.WrongSlaveIdWrite.dat ├── TModbusUnavailableRegistersAndHolesIntegrationTest.HolesAndUnavailable.dat ├── TModbusUnavailableRegistersIntegrationTest.UnavailableRegisterInTheMiddle.dat ├── TModbusUnavailableRegistersIntegrationTest.UnavailableRegisterOnBorder.dat ├── TModbusUnavailableRegistersIntegrationTest.UnsupportedRegisterOnBorder.dat ├── TNevaIntegrationTest.Poll.dat ├── TNevaTest.PrepareOk.dat ├── TNevaTest.SendPasswordError.dat ├── TNevaTest.StartSessionError.dat ├── TNevaTest.SwitchToProgModeError.dat ├── TPollTest.DisconnectedPollDelay.dat ├── TPollTest.OnlyEventsPollError.dat ├── TPollTest.ReconnectWithOnlyEvents.dat ├── TPollTest.SemiSporadicRegister.dat ├── TPollTest.SingleDeviceEnableEventsError.dat ├── TPollTest.SingleDeviceEventsAndBigReadTime.dat ├── TPollTest.SingleDeviceSeveralRegisters.dat ├── TPollTest.SingleDeviceSingleRegister.dat ├── TPollTest.SingleDeviceSingleRegisterWithBigReadTime.dat ├── TPollTest.SingleDeviceSingleRegisterWithEvents.dat ├── TPollTest.SingleDeviceSingleRegisterWithEventsAndErrors.dat ├── TPollTest.SingleDeviceSingleRegisterWithEventsAndPolling.dat ├── TPollTest.SingleDeviceSingleRegisterWithEventsAndPollingWithReadPeriod.dat ├── TPollTest.SingleDeviceSingleRegisterWithReadPeriod.dat ├── TPollTest.SuspendAndResume.dat ├── TPollTest.SuspendAndResumeByTimeout.dat ├── TPollTest.SuspendAndResumeWithEvents.dat ├── TPtyBasedFakeSerialTest.Expect.dat ├── TPtyBasedFakeSerialTest.Forward.dat ├── TPulsarDeviceTest.PulsarHeatMeterFloatQuery.dat ├── TReconnectDetectionTest.Reconnect.dat ├── TReconnectDetectionTest.ReconnectMiss.dat ├── TS2KDeviceTest.TestSetRelayState.dat ├── TS2KIntegrationTest.Poll.dat ├── TSerialClientIntegrationTest.ErrorValue.dat ├── TSerialClientIntegrationTest.Errors.dat ├── TSerialClientIntegrationTest.OffValue.dat ├── TSerialClientIntegrationTest.OnTopicWriteError.dat ├── TSerialClientIntegrationTest.OnValue.dat ├── TSerialClientIntegrationTest.OnValueError.dat ├── TSerialClientIntegrationTest.PollIntervalMissErrors.dat ├── TSerialClientIntegrationTest.RPCRequestTransceive.dat ├── TSerialClientIntegrationTest.Reconnect2.dat ├── TSerialClientIntegrationTest.ReconnectAfterNetworkDisconnect.dat ├── TSerialClientIntegrationTest.ReconnectCycles.dat ├── TSerialClientIntegrationTest.ReconnectMiss.dat ├── TSerialClientIntegrationTest.ReconnectOnPortWriteError.dat ├── TSerialClientIntegrationTest.ReconnectRegisterWithBigPollInterval.dat ├── TSerialClientIntegrationTest.ReconnectTimeout.dat ├── TSerialClientIntegrationTest.ReconnectTimeoutAndCycles.dat ├── TSerialClientIntegrationTest.Round.dat ├── TSerialClientIntegrationTest.SetupErrors.dat ├── TSerialClientIntegrationTest.SlaveIdCollision.dat ├── TSerialClientReopenTest.ReopenTimeout.dat ├── TSerialClientTest.BCD16.dat ├── TSerialClientTest.BCD24.dat ├── TSerialClientTest.BCD32.dat ├── TSerialClientTest.BCD8.dat ├── TSerialClientTest.Char8.dat ├── TSerialClientTest.Double64.dat ├── TSerialClientTest.Errors.dat ├── TSerialClientTest.Float32.dat ├── TSerialClientTest.Poll.dat ├── TSerialClientTest.PortOpenError.dat ├── TSerialClientTest.Round.dat ├── TSerialClientTest.S24.dat ├── TSerialClientTest.S32.dat ├── TSerialClientTest.S64.dat ├── TSerialClientTest.S8.dat ├── TSerialClientTest.String.dat ├── TSerialClientTest.U32.dat ├── TSerialClientTest.U64.dat ├── TSerialClientTest.U8.dat ├── TSerialClientTest.WordSwap.dat ├── TSerialClientTest.Write.dat ├── TSerialClientTest.offset.dat ├── TSerialClientTestWithSetupRegisters.SetupFail.dat ├── TSerialClientTestWithSetupRegisters.SetupOk.dat ├── TSerialPortTest.TestImxBug.dat ├── TSerialPortTest.TestSkipNoise.dat ├── TUnielDeviceTest.TestQuery.dat ├── TUnielDeviceTest.TestSetBrightness.dat ├── TUnielDeviceTest.TestSetParam.dat ├── TUnielDeviceTest.TestSetRelayState.dat ├── TUnielIntegrationTest.Poll.dat ├── a_ok_test.cpp ├── abt.sh ├── bin_utils_test.cpp ├── channel_value_test.cpp ├── common_utils_test.cpp ├── configs │ ├── config-collision-test.json │ ├── config-collision-test2.json │ ├── config-collision-test3.json │ ├── config-dlms-test.json │ ├── config-em-test.json │ ├── config-energomera-ce102m-test.json │ ├── config-energomera-test.json │ ├── config-lls-test.json │ ├── config-mercury200-test.json │ ├── config-mercury230-test.json │ ├── config-milur-test.json │ ├── config-modbus-bitmasks-test.json │ ├── config-modbus-bitmasks-u32-test.json │ ├── config-modbus-continuous-read-test.json │ ├── config-modbus-continuous-write-test.json │ ├── config-modbus-io-test.json │ ├── config-modbus-little-endian-test.json │ ├── config-modbus-partial-write-test.json │ ├── config-modbus-publish-test.json │ ├── config-modbus-reconnect.json │ ├── config-modbus-several-bitmasks-test.json │ ├── config-modbus-test.json │ ├── config-modbus-unavailable-registers-and-holes-test.json │ ├── config-modbus-unavailable-registers-test.json │ ├── config-neva-test.json │ ├── config-no-collision-test.json │ ├── config-rpc-test.json │ ├── config-s2k-test.json │ ├── config-test.json │ ├── config-uniel-test.json │ ├── parse_enum.json │ ├── parse_test.json │ ├── parse_test_modbus_write_address.json │ ├── parse_test_parameters_array.json │ ├── parse_test_rate_limit.json │ ├── parse_test_readonly_parameters.json │ ├── parse_test_setup.json │ ├── parse_test_setup_condition.json │ ├── reconnect_test_1_device.json │ ├── reconnect_test_2_devices.json │ ├── reconnect_test_ebadf.json │ ├── reconnect_test_network.json │ └── unsuccessful │ │ ├── unsuccessful-0.json │ │ ├── unsuccessful-1.json │ │ ├── unsuccessful-10.json │ │ ├── unsuccessful-11.json │ │ ├── unsuccessful-12.json │ │ ├── unsuccessful-13.json │ │ ├── unsuccessful-2.json │ │ ├── unsuccessful-3.json │ │ ├── unsuccessful-4.json │ │ ├── unsuccessful-5.json │ │ ├── unsuccessful-6.json │ │ ├── unsuccessful-7.json │ │ ├── unsuccessful-8.json │ │ └── unsuccessful-9.json ├── device-templates │ ├── config-invalid-channel-condition.json │ ├── config-invalid-param-condition.json │ ├── config-invalid-setup-condition.json │ ├── config-mercury230.json │ ├── config-modbus-i.json │ ├── config-modbus-o.json │ ├── config-msu34.json │ ├── config-msu34.json.wrong │ ├── config-parameters-array-invalid-address.json │ ├── config-parameters-array-invalid-id.json │ ├── config-parameters-array.json │ ├── config-parameters-object-invalid-name-deprecated.json │ ├── config-parameters-object-invalid-name.json │ ├── config-readonly-parameters.json │ ├── config-setup-items-with-condition.json │ ├── config-setup-items.json │ ├── config-subdevice.json │ ├── test-device-override.json │ └── test-device-override2.json ├── device_load_config_test.cpp ├── device_load_config_test │ ├── parameters_array_match_values.json │ ├── parameters_array_read_values.json │ ├── parameters_array_register_list.json │ ├── parameters_group_array_register_list.json │ ├── parameters_group_object_register_list.json │ ├── parameters_object_match_values.json │ ├── parameters_object_read_values.json │ ├── parameters_object_register_list.json │ └── templates │ │ ├── config-parameters-array.json │ │ ├── config-parameters-group-array.json │ │ ├── config-parameters-group-object.json │ │ └── config-parameters-object.json ├── device_templates_file_extension_test.cpp ├── dlms_test.cpp ├── dooya_test.cpp ├── em_integration.cpp ├── em_test.cpp ├── energomera_ce102m_test.cpp ├── energomera_test.cpp ├── expector.cpp ├── expector.h ├── expressions │ ├── bad.txt │ └── good.txt ├── expressions_test.cpp ├── fake_serial_device.cpp ├── fake_serial_device.h ├── fake_serial_port.cpp ├── fake_serial_port.h ├── hw-templates │ └── hw.json ├── ivtm_test.cpp ├── lls_test.cpp ├── main.cpp ├── mercury200_expectations.cpp ├── mercury200_expectations.h ├── mercury200_test.cpp ├── mercury230_expectations.cpp ├── mercury230_expectations.h ├── mercury230_test.cpp ├── milur_expectations.cpp ├── milur_expectations.h ├── milur_test.cpp ├── modbus_expectations.cpp ├── modbus_expectations.h ├── modbus_expectations_base.cpp ├── modbus_expectations_base.h ├── modbus_ext_common_test.cpp ├── modbus_io_expectations.cpp ├── modbus_io_expectations.h ├── modbus_io_test.cpp ├── modbus_tcp_test.cpp ├── modbus_test.cpp ├── neva_test.cpp ├── parser_test │ ├── merge_template_ok1.json │ ├── merge_template_ok10.json │ ├── merge_template_ok11.json │ ├── merge_template_ok12.json │ ├── merge_template_ok13.json │ ├── merge_template_ok2.json │ ├── merge_template_ok3.json │ ├── merge_template_ok4.json │ ├── merge_template_ok5.json │ ├── merge_template_ok6.json │ ├── merge_template_ok7.json │ ├── merge_template_ok8.json │ ├── merge_template_ok9.json │ ├── merge_template_res1.json │ ├── merge_template_res10.json │ ├── merge_template_res11.json │ ├── merge_template_res12.json │ ├── merge_template_res13.json │ ├── merge_template_res2.json │ ├── merge_template_res3.json │ ├── merge_template_res4.json │ ├── merge_template_res5.json │ ├── merge_template_res6.json │ ├── merge_template_res7.json │ ├── merge_template_res8.json │ ├── merge_template_res9.json │ └── templates │ │ ├── merge-condition.json │ │ ├── merge-simple-with-setup.json │ │ ├── merge-simple.json │ │ ├── merge-subdevice.json │ │ ├── merge-subdevice2.json │ │ ├── subdevice.json │ │ ├── with-conditions.json │ │ └── with-duplicate-params.json ├── poll_plan_test.cpp ├── poll_test.cpp ├── protocols │ └── fake.schema.json ├── pty_based_fake_serial.cpp ├── pty_based_fake_serial.h ├── pulsar_test.cpp ├── s2k_expectations.cpp ├── s2k_expectations.h ├── s2k_test.cpp ├── serial_client_test.cpp ├── serial_config_test.cpp ├── serial_port_test.cpp ├── somfy_test.cpp ├── tcp_port_test.cpp ├── test_utils.cpp ├── test_utils.h ├── translation-templates │ ├── templates1 │ │ └── config-translations.json │ ├── templates2 │ │ └── config-translations.json │ ├── tr1.json │ └── tr2.json ├── uniel_expectations.cpp ├── uniel_expectations.h ├── uniel_test.cpp └── windeco_test.cpp ├── wb-homa-icpdas.sh ├── wb-mqtt-serial-confed-common.schema.json ├── wb-mqtt-serial-device-template.schema.json ├── wb-mqtt-serial-dummy.schema.json ├── wb-mqtt-serial-ports.schema.json ├── wb-mqtt-serial-rpc-device-load-config-request.schema.json ├── wb-mqtt-serial-rpc-device-load-request.schema.json ├── wb-mqtt-serial-rpc-device-probe-request.schema.json ├── wb-mqtt-serial-rpc-device-set-poll-request.schema.json ├── wb-mqtt-serial-rpc-device-set-request.schema.json ├── wb-mqtt-serial-rpc-port-load-request.schema.json ├── wb-mqtt-serial-rpc-port-scan-request.schema.json ├── wb-mqtt-serial-rpc-port-setup-request.schema.json └── wb-mqtt-serial.wbconfigs /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # See https://docs.github.com/ for more info about CODEOWNERS syntax 2 | * @KraPete @sikmir @u236 3 | 4 | templates/ @wirenboard/wb-templates 5 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 7 | ___________________________________ 8 | **Что происходит; кому и зачем нужно:** 9 | 10 | 11 | ___________________________________ 12 | **Что поменялось для пользователей:** 13 | 14 | 15 | ___________________________________ 16 | **Как проверял/а:** 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | test/wb-homa-test 3 | *.deb 4 | debian/files 5 | *.build 6 | *.buildinfo 7 | *.changes 8 | *.dsc 9 | */core.* 10 | *.tar.gz 11 | *.debhelper.log 12 | *.debhelper 13 | debian/*.substvars 14 | debian/wb-mqtt-serial/ 15 | debian/tmp/ 16 | .d 17 | vgcore.* 18 | test/*.out 19 | 20 | **/.vscode/* 21 | workspace.xml 22 | **/.cproject 23 | **/.project 24 | **/.settings 25 | .idea 26 | .devcontainer 27 | .zed 28 | 29 | # core 30 | *.core 31 | 32 | debhelper-build-stamp 33 | .clang-* 34 | build 35 | compile_commands.json 36 | 37 | ### direnv ### 38 | .direnv 39 | .envrc 40 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/gurux"] 2 | path = thirdparty/gurux 3 | url = git@github.com:wirenboard/Gurux.DLMS.cpp.git 4 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | buildDebSbuild defaultTargets: 'bullseye-armhf bullseye-arm64', 2 | defaultRunLintian: true, 3 | defaultStyleCheckDirs: 'src test', 4 | defaultRunCoverage: true, 5 | defaultCoverageMin: '73', 6 | defaultDoCoverallsReporting: true, 7 | defaultBuildNode: 'heavy-duty' 8 | -------------------------------------------------------------------------------- /configs/config.json.default: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "port_type" : "serial", 6 | "path" : "/dev/ttyNSC0", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 2, 11 | "enabled": false, 12 | "devices" : [ 13 | { 14 | "device_type" : "WB-MRM2", 15 | "slave_id": "0x01", 16 | "enabled": false 17 | } 18 | ] 19 | } 20 | 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /configs/config.json.wb234: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "port_type" : "serial", 6 | "path" : "/dev/ttyNSC0", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 2, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "device_type" : "WB-MRM2", 15 | "slave_id": "0x01", 16 | "enabled": false 17 | } 18 | ] 19 | }, 20 | { 21 | "path" : "/dev/ttyNSC1", 22 | "baud_rate": 9600, 23 | "parity": "N", 24 | "data_bits": 8, 25 | "stop_bits": 2, 26 | "enabled": true, 27 | "devices" : [] 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /configs/config.json.wb5: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "port_type" : "serial", 6 | "path" : "/dev/ttyAPP1", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 2, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "device_type" : "WB-MRM2", 15 | "slave_id": "0x01", 16 | "enabled": false 17 | } 18 | ] 19 | }, 20 | { 21 | 22 | "path" : "/dev/ttyAPP4", 23 | "baud_rate": 9600, 24 | "parity": "N", 25 | "data_bits": 8, 26 | "stop_bits": 2, 27 | "enabled": true, 28 | "devices" : [] 29 | }, 30 | { 31 | 32 | "path" : "/dev/ttyAPP2", 33 | "baud_rate": 9600, 34 | "parity": "N", 35 | "data_bits": 8, 36 | "stop_bits": 2, 37 | "enabled": false, 38 | "devices" : [] 39 | }, 40 | { 41 | 42 | "path" : "/dev/ttyAPP3", 43 | "baud_rate": 9600, 44 | "parity": "N", 45 | "data_bits": 8, 46 | "stop_bits": 2, 47 | "enabled": false, 48 | "devices" : [] 49 | } 50 | 51 | 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /configs/config.json.wb8: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "path": "/dev/ttyRS485-1", 6 | "baud_rate": 9600, 7 | "parity": "N", 8 | "data_bits": 8, 9 | "stop_bits": 2, 10 | "enabled": true, 11 | "devices": [] 12 | }, 13 | { 14 | "path": "/dev/ttyRS485-2", 15 | "baud_rate": 9600, 16 | "parity": "N", 17 | "data_bits": 8, 18 | "stop_bits": 2, 19 | "enabled": true, 20 | "devices": [] 21 | }, 22 | { 23 | "path": "/dev/ttyMOD1", 24 | "baud_rate": 9600, 25 | "parity": "N", 26 | "data_bits": 8, 27 | "stop_bits": 2, 28 | "enabled": false, 29 | "devices": [] 30 | }, 31 | { 32 | "path": "/dev/ttyMOD2", 33 | "baud_rate": 9600, 34 | "parity": "N", 35 | "data_bits": 8, 36 | "stop_bits": 2, 37 | "enabled": false, 38 | "devices": [] 39 | }, 40 | { 41 | "path": "/dev/ttyMOD3", 42 | "baud_rate": 9600, 43 | "parity": "N", 44 | "data_bits": 8, 45 | "stop_bits": 2, 46 | "enabled": false, 47 | "devices": [] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: wb-mqtt-serial 2 | Maintainer: Wiren Board team 3 | Section: misc 4 | Priority: optional 5 | Standards-Version: 3.9.2 6 | Build-Depends: debhelper (>= 10), 7 | gcovr:all, 8 | j2cli:all, 9 | libgtest-dev, 10 | libwbmqtt1-5-dev (>= 5.3.2~~), 11 | libwbmqtt1-5-test-utils (>= 5.3.2~~), 12 | pkg-config 13 | Homepage: https://github.com/wirenboard/wb-mqtt-serial 14 | 15 | Package: wb-mqtt-serial 16 | Architecture: any 17 | Depends: ${shlibs:Depends}, ${misc:Depends}, ucf, bsdutils (>= 2.29), wb-utils 18 | Replaces: wb-homa-modbus (<< 1.14.1) 19 | Recommends: wb-mqtt-confed (>= 1.7.0) 20 | Breaks: wb-homa-modbus (<< 1.14.1), wb-mqtt-confed (<< 1.7.0), wb-mqtt-homeui (<< 2.107.0~~) 21 | Description: Wiren Board Smart Home MQTT serial protocol driver 22 | wb-mqtt-serial is a service which communicates with devices on RS-485 23 | via Modbus or other supported protocols. Modbus TCP is also supported. 24 | You can add your devices by creating new templates and configure each 25 | register poll settings individually. Also it contains advanced templates 26 | to configure parameters of Wiren Board peripheral devices. 27 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wirenboard/wb-mqtt-serial/19215edabf3f2df9ad0a585b681033dcd9c4886e/debian/copyright -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | COV_FAIL_UNDER := $(patsubst cov-fail-under=%,%,$(filter cov-fail-under=%,$(DEB_BUILD_OPTIONS))) 4 | COV_REPORT := $(patsubst cov-report=%,%,$(filter cov-report=%,$(DEB_BUILD_OPTIONS))) 5 | 6 | ifneq ($(COV_FAIL_UNDER),) 7 | MAKEFLAGS += COV_FAIL_UNDER=$(COV_FAIL_UNDER) 8 | endif 9 | ifneq ($(COV_REPORT),) 10 | MAKEFLAGS += COV_REPORT=$(COV_REPORT) 11 | endif 12 | ifneq (,$(findstring debug, $(DEB_BUILD_OPTIONS))) 13 | MAKEFLAGS += DEBUG=1 14 | endif 15 | 16 | %: 17 | dh $@ --parallel 18 | 19 | override_dh_installinit: 20 | dh_installinit --noscripts 21 | 22 | override_dh_systemd_start: 23 | dh_systemd_start --no-restart-after-upgrade 24 | 25 | override_dh_systemd_enable: 26 | dh_systemd_enable --name=wb-mqtt-serial 27 | -------------------------------------------------------------------------------- /debian/wb-mqtt-serial.dirs: -------------------------------------------------------------------------------- 1 | usr/bin 2 | etc 3 | etc/wb-configs.d 4 | usr/share/wb-mqtt-serial 5 | var/lib/wb-mqtt-serial 6 | var/lib/wb-mqtt-serial/schemas 7 | -------------------------------------------------------------------------------- /debian/wb-mqtt-serial.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | rm -f /usr/share/wb-mqtt-confed/schemas/wb-mqtt-serial.schema.json 6 | 7 | #DEBHELPER# 8 | -------------------------------------------------------------------------------- /debian/wb-mqtt-serial.postrm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | CONFFILE=/etc/wb-mqtt-serial.conf 6 | 7 | if [ "$1" = "purge" ]; then 8 | if which ucf >/dev/null; then 9 | ucf --purge $CONFFILE 10 | rm -f $CONFFILE 11 | rm -f $CONFFILE.simple 12 | rm -f $CONFFILE.default 13 | fi 14 | fi 15 | 16 | rm -f /usr/share/wb-mqtt-confed/schemas/wb-mqtt-serial.schema.json 17 | rm -f /var/lib/wb-mqtt-confed/schemas/wb-mqtt-serial.schema.json 18 | 19 | #DEBHELPER# 20 | -------------------------------------------------------------------------------- /debian/wb-mqtt-serial.wb-mqtt-serial.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=MQTT Driver for serial devices 3 | Wants=wb-hwconf-manager.service wb-modules.service 4 | After=network.target wb-hwconf-manager.service wb-modules.service 5 | 6 | [Service] 7 | Type=simple 8 | Restart=on-failure 9 | RestartSec=1 10 | User=root 11 | ExecStart=/usr/bin/wb-mqtt-serial 12 | ExecStartPre=/usr/lib/wb-mqtt-serial/generate-system-config.sh 13 | 14 | [Install] 15 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /doc/timeouts.puml: -------------------------------------------------------------------------------- 1 | @startuml Timeouts 2 | 3 | start 4 | 5 | repeat 6 | #BurlyWood :Подождать "poll_interval"; 7 | while (Есть регистры для опроса?) 8 | if (Устройство было отключено?) then (да) 9 | while (Есть регистры для записи в устройство?) 10 | #BurlyWood :Подождать "frame_timeout_ms" (по умолчанию **0 мс или задано протоколом**); 11 | #BurlyWood :Подождать "guard_interval_us" (по умолчанию **0 мкс**); 12 | :Записать регистр; 13 | #BurlyWood :Ожидание подтвержения записи в течение "response_timeout_ms" (по умолчанию **500 мс**); 14 | endwhile 15 | else (нет) 16 | endif 17 | #BurlyWood :Подождать "frame_timeout_ms" (по умолчанию **0 мс или задано протоколом**); 18 | #BurlyWood :Подождать "guard_interval_us" (по умолчанию **0 мкс**); 19 | :Послать запрос на чтение регистров; 20 | #BurlyWood :Ожидание данных регистров в течение "response_timeout_ms" (по умолчанию **500 мс**); 21 | endwhile 22 | repeat while () 23 | 24 | stop 25 | 26 | @enduml -------------------------------------------------------------------------------- /generate-system-config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CONFFILE=/etc/wb-mqtt-serial.conf 4 | 5 | [ -f "$CONFFILE" ] && exit 0 6 | 7 | . /usr/lib/wb-utils/wb_env.sh 8 | 9 | wb_source "of" 10 | 11 | if of_machine_match "wirenboard,wirenboard-85x"; then 12 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.wb85" 13 | elif of_machine_match "wirenboard,wirenboard-8xx"; then 14 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.wb8" 15 | elif of_machine_match "wirenboard,wirenboard-720"; then 16 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.wb7" 17 | elif of_machine_match "contactless,imx6ul-wirenboard670"; then 18 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.wb67" 19 | elif of_machine_match "contactless,imx6ul-wirenboard60"; then 20 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.wb6" 21 | elif of_machine_match "contactless,imx28-wirenboard50"; then 22 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.wb5" 23 | elif of_machine_match "contactless,imx23-wirenboard41" || 24 | of_machine_match "contactless,imx23-wirenboard32" || 25 | of_machine_match "contactless,imx23-wirenboard28"; 26 | then 27 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.wb234" 28 | else 29 | BOARD_CONF="/usr/share/wb-mqtt-serial/wb-mqtt-serial.conf.default" 30 | fi 31 | 32 | cp "$BOARD_CONF" "$CONFFILE" 33 | -------------------------------------------------------------------------------- /protocols/dlms.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom DLMS device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/dlms_device_properties" }, 8 | { "$ref": "#/definitions/dlms_channels" }, 9 | { "$ref": "#/definitions/slave_id" }, 10 | { "$ref": "#/definitions/no_setup" } 11 | ], 12 | "properties": { 13 | "protocol": { 14 | "type": "string", 15 | "enum": ["dlms"], 16 | "options": { 17 | "hidden": true 18 | } 19 | } 20 | }, 21 | "required": ["protocol", "slave_id"], 22 | "options": { 23 | "disable_edit_json": true, 24 | "compact": true, 25 | "disable_collapse": true, 26 | "wb": { 27 | "disable_panel": true 28 | } 29 | }, 30 | "defaultProperties": ["slave_id", "channels", "protocol"], 31 | "translations": { 32 | "ru": { 33 | "Custom DLMS device": "Устройство с протоколом DLMS/СПОДЭС" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /protocols/energomera-c.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Energomera device with IEC 61107 Mode C protocol", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/channels_with_string_addresses" }, 9 | { "$ref": "#/definitions/slave_id_broadcast" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["energomera_iec_mode_c"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Energomera device with IEC 61107 Mode C protocol": "Счётчик Энергомера с протоколом IEC 61107 Mode C" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/energomera.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Energomera device with IEC 61107 fast read support", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id_broadcast" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["energomera_iec"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Energomera device with IEC 61107 fast read support": "Счётчик Энергомера с поддержкой быстрого чтения по протоколу IEC 61107" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/iec-c.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom device with IEC 61107 Mode C protocol", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/channels_with_string_addresses" }, 9 | { "$ref": "#/definitions/slave_id_broadcast" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["iec_mode_c"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom device with IEC 61107 Mode C protocol": "Устройство с протоколом IEC 61107 Mode C" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/ivtm.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom IVTM device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["ivtm"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom IVTM device": "Устройство с протоколом ИВТМ" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/lls.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom LLS device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["lls"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom LLS device": "Устройство с протоколом LLS" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/mercury200.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Mercury 200 device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["mercury200"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Mercury 200 device": "Устройство с протоколом счётчика Меркурий 200" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/mercury230.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Mercury 230 device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id_broadcast" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["mercury230"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Mercury 230 device": "Устройство с протоколом счётчика Меркурий 230" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/milur.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Milur device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["milur"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Milur device": "Устройство с протоколом счётчика Милур" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/modbus-io.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Modbus IO device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/common_channels" }, 8 | { "$ref": "#/definitions/common_setup" }, 9 | { "$ref": "#/definitions/slave_id" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["modbus_io"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Modbus IO device": "Устройство с протоколом Modbus IO" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/neva.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Neva device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id_broadcast" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["neva"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Neva device": "Счётчик Нева" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/pulsar.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom Pulsar device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["pulsar"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom Pulsar device": "Устройство с протоколом Пульсар" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/s2k.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom S2K device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/no_setup" }, 8 | { "$ref": "#/definitions/common_channels" }, 9 | { "$ref": "#/definitions/slave_id" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["s2k"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom S2K device": "Устройство с протоколом С2000" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /protocols/uniel.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Custom UNIEL device", 5 | "allOf": [ 6 | { "$ref": "#/definitions/deviceProperties" }, 7 | { "$ref": "#/definitions/common_channels" }, 8 | { "$ref": "#/definitions/slave_id" }, 9 | { "$ref": "#/definitions/no_setup" } 10 | ], 11 | "properties": { 12 | "protocol": { 13 | "type": "string", 14 | "enum": ["uniel"], 15 | "options": { 16 | "hidden": true 17 | } 18 | } 19 | }, 20 | "required": ["protocol", "slave_id"], 21 | "options": { 22 | "disable_edit_json": true, 23 | "compact": true, 24 | "disable_collapse": true, 25 | "wb": { 26 | "disable_panel": true 27 | } 28 | }, 29 | "defaultProperties": ["slave_id", "channels", "protocol"], 30 | "translations": { 31 | "ru": { 32 | "Custom UNIEL device": "Устройство с протоколом UNIEL" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/bcd_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef WB_MQTT_SERIAL_BCD_UTILS_H 2 | #define WB_MQTT_SERIAL_BCD_UTILS_H 3 | 4 | #include 5 | #include 6 | 7 | enum class WordSizes 8 | { 9 | W8_SZ = 1, 10 | W16_SZ = 2, 11 | W24_SZ = 3, 12 | W32_SZ = 4, 13 | }; 14 | 15 | // Alignment independent cast of up to four bytes to uint32_t. 16 | // Resulting uint32_t is (potentially) zero padded image of the original BCD byte array. 17 | // For example, BCD32 {0x00, 0x12, 0x34, 0x56} converted to little endian integer 18 | // 0x00123456 (bytes {0x56, 0x34, 0x12, 0x00} or big endian integer 0x00123456 19 | // (bytes {0x00, 0x12, 0x34, 0x56}). 20 | uint32_t PackBytes(uint8_t* bytes, WordSizes size); 21 | // Accepts uint64_t that is a (potentially) zero padded byte image of original BCD byte array 22 | // converted to uint32_t by previous function. 23 | uint64_t PackedBCD2Int(uint64_t packed, WordSizes size); 24 | 25 | std::vector IntToBCDArray(uint64_t value, WordSizes size); 26 | 27 | uint32_t IntToPackedBCD(uint32_t value, WordSizes size); 28 | #endif // WB_MQTT_SERIAL_BCD_UTILS_H 29 | -------------------------------------------------------------------------------- /src/confed_channel_modes.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | Json::Value ConfigToHomeuiSubdeviceChannel(const Json::Value& channel); 4 | Json::Value ConfigToHomeuiGroupChannel(const Json::Value& channel, size_t channelIndex); 5 | Json::Value HomeuiToConfigChannel(const Json::Value& channel); 6 | void AddChannelModes(Json::Value& channelSchema); 7 | -------------------------------------------------------------------------------- /src/confed_config_generator.h: -------------------------------------------------------------------------------- 1 | #include "serial_config.h" 2 | 3 | Json::Value MakeConfigFromConfed(std::istream& stream, TTemplateMap& templates); 4 | -------------------------------------------------------------------------------- /src/confed_config_generator_with_groups.h: -------------------------------------------------------------------------------- 1 | #include "serial_config.h" 2 | 3 | void MakeDeviceWithGroupsConfigFromConfed(Json::Value& device, const Json::Value& deviceTemplate); 4 | -------------------------------------------------------------------------------- /src/confed_device_schemas_map.cpp: -------------------------------------------------------------------------------- 1 | #include "confed_device_schemas_map.h" 2 | #include "confed_schema_generator.h" 3 | 4 | TDevicesConfedSchemasMap::TDevicesConfedSchemasMap(TTemplateMap& templatesMap, 5 | TSerialDeviceFactory& deviceFactory, 6 | const Json::Value& commonDeviceSchema) 7 | : TemplatesMap(templatesMap), 8 | CommonDeviceSchema(commonDeviceSchema), 9 | DeviceFactory(deviceFactory) 10 | {} 11 | 12 | std::shared_ptr TDevicesConfedSchemasMap::GetSchema(const std::string& deviceType) 13 | { 14 | std::unique_lock lock(Mutex); 15 | try { 16 | return Schemas.at(deviceType); 17 | } catch (const std::out_of_range&) { 18 | auto deviceTemplate = TemplatesMap.GetTemplate(deviceType); 19 | auto schema = 20 | std::make_shared(GenerateSchemaForConfed(*deviceTemplate, DeviceFactory, CommonDeviceSchema)); 21 | Schemas.emplace(deviceType, schema); 22 | return schema; 23 | } 24 | } 25 | 26 | void TDevicesConfedSchemasMap::InvalidateCache(const std::string& deviceType) 27 | { 28 | std::unique_lock lock(Mutex); 29 | Schemas.erase(deviceType); 30 | } 31 | -------------------------------------------------------------------------------- /src/confed_device_schemas_map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serial_config.h" 4 | #include "templates_map.h" 5 | 6 | class TDevicesConfedSchemasMap 7 | { 8 | TTemplateMap& TemplatesMap; 9 | const Json::Value& CommonDeviceSchema; 10 | TSerialDeviceFactory& DeviceFactory; 11 | 12 | //! Device type to schema map 13 | std::unordered_map> Schemas; 14 | 15 | std::mutex Mutex; 16 | 17 | public: 18 | TDevicesConfedSchemasMap(TTemplateMap& templatesMap, 19 | TSerialDeviceFactory& deviceFactory, 20 | const Json::Value& commonDeviceSchema); 21 | 22 | /** 23 | * @brief Get the json-schema for specified device type 24 | * 25 | * @throws std::out_of_range if nothing found 26 | */ 27 | std::shared_ptr GetSchema(const std::string& deviceType); 28 | 29 | void InvalidateCache(const std::string& deviceType); 30 | }; 31 | -------------------------------------------------------------------------------- /src/confed_json_generator.h: -------------------------------------------------------------------------------- 1 | #include "serial_config.h" 2 | 3 | Json::Value MakeJsonForConfed(const std::string& configFileName, TTemplateMap& templates); 4 | -------------------------------------------------------------------------------- /src/confed_json_generator_with_groups.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | Json::Value MakeDeviceWithGroupsForConfed(const Json::Value& config, const Json::Value& deviceTemplateSchema); 4 | -------------------------------------------------------------------------------- /src/confed_protocol_schemas_map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct TProtocolConfedSchema 7 | { 8 | std::string Type; 9 | 10 | TProtocolConfedSchema(const std::string& type, 11 | const std::unordered_map& titleTranslations, 12 | const std::string& filePath); 13 | 14 | std::string GetTitle(const std::string& lang = std::string("en")) const; 15 | const std::string& GetFilePath() const; 16 | 17 | private: 18 | std::unordered_map Title; 19 | std::string FilePath; 20 | }; 21 | 22 | class TProtocolConfedSchemasMap 23 | { 24 | //! Protocol to TProtocolConfedSchema map 25 | std::unordered_map Schemas; 26 | 27 | //! Protocol to JSON-Schema map 28 | std::unordered_map JsonSchemas; 29 | 30 | const Json::Value& CommonDeviceSchema; 31 | 32 | public: 33 | TProtocolConfedSchemasMap(const std::string& protocolTemplatesFolder, const Json::Value& commonDeviceSchema); 34 | 35 | void AddFolder(const std::string& protocolTemplatesFolder); 36 | 37 | const std::unordered_map& GetSchemas() const; 38 | 39 | const Json::Value& GetSchema(const std::string& protocol); 40 | }; 41 | -------------------------------------------------------------------------------- /src/confed_schema_generator_with_groups.h: -------------------------------------------------------------------------------- 1 | #include "serial_config.h" 2 | 3 | std::string GetChannelPropertyName(size_t index); 4 | 5 | Json::Value MakeDeviceWithGroupsUISchema(TDeviceTemplate& deviceTemplate, 6 | TSerialDeviceFactory& deviceFactory, 7 | const Json::Value& commonDeviceSchema); 8 | -------------------------------------------------------------------------------- /src/config_merge_template.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "expression_evaluator.h" 4 | #include "serial_config.h" 5 | 6 | Json::Value MergeDeviceConfigWithTemplate(const Json::Value& deviceData, 7 | const std::string& deviceType, 8 | const Json::Value& deviceTemplate); 9 | 10 | typedef std::unordered_map> TExpressionsCache; 11 | 12 | class TJsonParams: public Expressions::IParams 13 | { 14 | const Json::Value& Params; 15 | 16 | public: 17 | explicit TJsonParams(const Json::Value& params); 18 | 19 | std::optional Get(const std::string& name) const override; 20 | }; 21 | 22 | bool CheckCondition(const Json::Value& item, const TJsonParams& params, TExpressionsCache* exprs); 23 | -------------------------------------------------------------------------------- /src/config_schema_generator.h: -------------------------------------------------------------------------------- 1 | #include "confed_protocol_schemas_map.h" 2 | #include "serial_config.h" 3 | 4 | void ValidateConfig(const Json::Value& config, 5 | TSerialDeviceFactory& deviceFactory, 6 | const Json::Value& commonDeviceSchema, 7 | const Json::Value& portsSchema, 8 | TTemplateMap& templates, 9 | TProtocolConfedSchemasMap& protocolSchemas); 10 | -------------------------------------------------------------------------------- /src/crc16.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CRC16 6 | { 7 | uint16_t CalculateCRC16(const uint8_t* buffer, uint16_t len); 8 | } 9 | -------------------------------------------------------------------------------- /src/definitions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class TBinarySemaphore; 7 | 8 | using TTimePoint = std::chrono::steady_clock::time_point; 9 | using PBinarySemaphore = std::shared_ptr; 10 | -------------------------------------------------------------------------------- /src/device_template_generator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum TDeviceTemplateGenerationMode 6 | { 7 | PRINT = 0, //! Print information about generation source to stdout 8 | VERBOSE_PRINT, //! Print verbose information about generation source to stdout 9 | GENERATE_TEMPLATE, //! Generate device template file 10 | MAX_DEVICE_TEMPLATE_GENERATION_MODE 11 | }; 12 | 13 | /** 14 | * @brief Generate device template file 15 | * 16 | * @param appName - apptication name 17 | * @param destinationDir - directory to store generated template 18 | * @param options - command line options 19 | */ 20 | void GenerateDeviceTemplate(const std::string& appName, const std::string& destinationDir, const char* options); -------------------------------------------------------------------------------- /src/devices/curtains/windeco_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serial_config.h" 4 | 5 | namespace WinDeco 6 | { 7 | class TDevice: public TSerialDevice, public TUInt32SlaveId 8 | { 9 | uint8_t ZoneId; 10 | uint8_t CurtainId; 11 | 12 | std::vector OpenCommand; 13 | std::vector CloseCommand; 14 | std::vector GetPositionCommand; 15 | std::vector GetStateCommand; 16 | 17 | std::vector ExecCommand(TPort& port, const std::vector& request); 18 | 19 | public: 20 | TDevice(PDeviceConfig config, PProtocol protocol); 21 | 22 | static void Register(TSerialDeviceFactory& factory); 23 | 24 | protected: 25 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 26 | void WriteRegisterImpl(TPort& port, const TRegisterConfig& reg, const TRegisterValue& regValue) override; 27 | }; 28 | 29 | std::vector MakeRequest(uint8_t zoneId, uint8_t curtainId, uint8_t command); 30 | size_t ParsePositionResponse(uint8_t zoneId, uint8_t curtainId, const std::vector& bytes); 31 | uint8_t ParseStateResponse(uint8_t zoneId, uint8_t curtainId, const std::vector& bytes); 32 | } 33 | -------------------------------------------------------------------------------- /src/devices/energomera_ce_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serial_config.h" 4 | 5 | class TEnergomeraCeDevice: public TSerialDevice, public TUInt32SlaveId 6 | { 7 | public: 8 | TEnergomeraCeDevice(PDeviceConfig config, PProtocol protocol); 9 | 10 | static void Register(TSerialDeviceFactory& factory); 11 | 12 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 13 | }; 14 | 15 | typedef std::shared_ptr PEnergomeraCeDevice; 16 | -------------------------------------------------------------------------------- /src/devices/energomera_iec_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iec_common.h" 4 | #include "serial_config.h" 5 | 6 | class TEnergomeraIecWithFastReadDevice: public TIEC61107Device 7 | { 8 | public: 9 | TEnergomeraIecWithFastReadDevice(PDeviceConfig device_config, PProtocol protocol); 10 | 11 | PRegisterRange CreateRegisterRange() const override; 12 | void ReadRegisterRange(TPort& port, PRegisterRange range, bool breakOnError = false) override; 13 | 14 | static void Register(TSerialDeviceFactory& factory); 15 | 16 | protected: 17 | void PrepareImpl(TPort& port) override; 18 | void EndSession(TPort& port) override; 19 | }; 20 | -------------------------------------------------------------------------------- /src/devices/energomera_iec_mode_c_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iec_common.h" 4 | #include "serial_config.h" 5 | 6 | class TEnergomeraIecModeCDevice: public TIEC61107ModeCDevice 7 | { 8 | public: 9 | TEnergomeraIecModeCDevice(PDeviceConfig device_config, PProtocol protocol); 10 | 11 | static void Register(TSerialDeviceFactory& factory); 12 | 13 | private: 14 | std::string GetParameterRequest(const TRegisterConfig& reg) const override; 15 | TRegisterValue GetRegisterValue(const TRegisterConfig& reg, const std::string& value) override; 16 | }; -------------------------------------------------------------------------------- /src/devices/iec_mode_c_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iec_common.h" 4 | #include "serial_config.h" 5 | 6 | class TIecModeCDevice: public TIEC61107ModeCDevice 7 | { 8 | public: 9 | TIecModeCDevice(PDeviceConfig device_config, PProtocol protocol); 10 | 11 | static void Register(TSerialDeviceFactory& factory); 12 | 13 | protected: 14 | void PrepareImpl(TPort& port) override; 15 | 16 | private: 17 | std::string GetParameterRequest(const TRegisterConfig& reg) const override; 18 | TRegisterValue GetRegisterValue(const TRegisterConfig& reg, const std::string& value) override; 19 | }; -------------------------------------------------------------------------------- /src/devices/ivtm_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serial_config.h" 4 | #include "serial_device.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class TIVTMDevice: public TSerialDevice, public TUInt32SlaveId 11 | { 12 | public: 13 | TIVTMDevice(PDeviceConfig config, PProtocol protocol); 14 | 15 | static void Register(TSerialDeviceFactory& factory); 16 | 17 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 18 | 19 | private: 20 | void WriteCommand(TPort& port, uint16_t addr, uint16_t data_addr, uint8_t data_len); 21 | void ReadResponse(TPort& port, uint16_t addr, uint8_t* payload, uint16_t len); 22 | 23 | uint8_t DecodeASCIIByte(uint8_t* buf); 24 | uint16_t DecodeASCIIWord(uint8_t* buf); 25 | bool DecodeASCIIBytes(uint8_t* buf, uint8_t* result, uint8_t len_bytes); 26 | }; 27 | 28 | typedef std::shared_ptr PIVTMDevice; 29 | -------------------------------------------------------------------------------- /src/devices/lls_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serial_config.h" 4 | #include "serial_device.h" 5 | 6 | class TLLSDevice: public TSerialDevice, public TUInt32SlaveId 7 | { 8 | public: 9 | TLLSDevice(PDeviceConfig config, PProtocol protocol); 10 | 11 | std::chrono::milliseconds GetFrameTimeout(TPort& port) const override; 12 | 13 | static void Register(TSerialDeviceFactory& factory); 14 | 15 | protected: 16 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 17 | void InvalidateReadCache() override; 18 | 19 | private: 20 | std::unordered_map> CmdResultCache; 21 | 22 | std::vector ExecCommand(TPort& port, uint8_t cmd); 23 | }; 24 | -------------------------------------------------------------------------------- /src/devices/mercury200_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "serial_config.h" 14 | #include "serial_device.h" 15 | 16 | class TMercury200Device: public TSerialDevice, public TUInt32SlaveId 17 | { 18 | public: 19 | TMercury200Device(PDeviceConfig config, PProtocol protocol); 20 | 21 | static void Register(TSerialDeviceFactory& factory); 22 | 23 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 24 | void InvalidateReadCache() override; 25 | 26 | std::chrono::milliseconds GetFrameTimeout(TPort& port) const override; 27 | 28 | private: 29 | std::vector ExecCommand(TPort& port, uint8_t cmd); 30 | // buf expected to be 7 bytes long 31 | void FillCommand(uint8_t* buf, uint32_t id, uint8_t cmd) const; 32 | int RequestResponse(TPort& port, uint32_t slave, uint8_t cmd, uint8_t* response) const; 33 | bool IsBadHeader(uint32_t slave_expected, uint8_t cmd_expected, uint8_t* response) const; 34 | 35 | bool IsCrcValid(uint8_t* buf, int sz) const; 36 | 37 | std::unordered_map> CmdResultCache; 38 | }; 39 | 40 | typedef std::shared_ptr PMercury200Device; 41 | -------------------------------------------------------------------------------- /src/devices/milur_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "em_device.h" 9 | #include "serial_config.h" 10 | 11 | class TMilurDevice: public TEMDevice 12 | { 13 | public: 14 | enum RegisterType 15 | { 16 | REG_PARAM = 0, 17 | REG_POWER, 18 | REG_ENERGY, 19 | REG_FREQ, 20 | REG_POWERFACTOR 21 | }; 22 | 23 | TMilurDevice(PDeviceConfig device_config, PProtocol protocol); 24 | 25 | static void Register(TSerialDeviceFactory& factory); 26 | 27 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 28 | 29 | std::chrono::milliseconds GetFrameTimeout(TPort& port) const override; 30 | 31 | protected: 32 | void PrepareImpl(TPort& port) override; 33 | bool ConnectionSetup(TPort& port) override; 34 | ErrorType CheckForException(uint8_t* frame, int len, const char** message) override; 35 | uint64_t BuildIntVal(uint8_t* p, int sz) const; 36 | uint64_t BuildBCB32(uint8_t* psrc) const; 37 | int GetExpectedSize(int type) const; 38 | }; 39 | 40 | typedef std::shared_ptr PMilurDevice; 41 | -------------------------------------------------------------------------------- /src/devices/modbus_io_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "modbus_device.h" 9 | #include "running_average.h" 10 | 11 | class TModbusIODevice: public TSerialDevice, public TUInt32SlaveId 12 | { 13 | std::unique_ptr ModbusTraits; 14 | int Shift = 0; 15 | Modbus::TRegisterCache ModbusCache; 16 | TRunningAverage ResponseTime; 17 | 18 | public: 19 | TModbusIODevice(std::unique_ptr modbusTraits, 20 | const TModbusDeviceConfig& config, 21 | PProtocol protocol); 22 | 23 | PRegisterRange CreateRegisterRange() const override; 24 | void ReadRegisterRange(TPort& port, PRegisterRange range, bool breakOnError = false) override; 25 | void WriteSetupRegisters(TPort& port, const TDeviceSetupItems& setupItems, bool breakOnError = false) override; 26 | 27 | std::chrono::milliseconds GetFrameTimeout(TPort& port) const override; 28 | 29 | static void Register(TSerialDeviceFactory& factory); 30 | 31 | protected: 32 | void PrepareImpl(TPort& port) override; 33 | void WriteRegisterImpl(TPort& port, const TRegisterConfig& reg, const TRegisterValue& value) override; 34 | }; 35 | -------------------------------------------------------------------------------- /src/devices/neva_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iec_common.h" 4 | #include "serial_config.h" 5 | 6 | class TNevaDevice: public TIEC61107ModeCDevice 7 | { 8 | public: 9 | TNevaDevice(PDeviceConfig device_config, PProtocol protocol); 10 | 11 | static void Register(TSerialDeviceFactory& factory); 12 | 13 | private: 14 | std::string GetParameterRequest(const TRegisterConfig& reg) const override; 15 | TRegisterValue GetRegisterValue(const TRegisterConfig& reg, const std::string& value) override; 16 | }; 17 | -------------------------------------------------------------------------------- /src/devices/s2k_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "serial_config.h" 9 | #include "serial_device.h" 10 | 11 | class TS2KDevice: public TSerialDevice, public TUInt32SlaveId 12 | { 13 | public: 14 | enum RegisterType 15 | { 16 | REG_RELAY = 0, 17 | REG_RELAY_MODE, 18 | REG_RELAY_DEFAULT, 19 | REG_RELAY_DELAY, 20 | }; 21 | 22 | TS2KDevice(PDeviceConfig config, PProtocol protocol); 23 | 24 | static void Register(TSerialDeviceFactory& factory); 25 | 26 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 27 | 28 | protected: 29 | void WriteRegisterImpl(TPort& port, const TRegisterConfig& reg, const TRegisterValue& value) override; 30 | 31 | private: 32 | uint8_t CrcS2K(const uint8_t* array, int size); 33 | 34 | static uint8_t CrcTable[]; 35 | uint8_t RelayState[5]; 36 | }; 37 | 38 | typedef std::shared_ptr PS2KDevice; 39 | -------------------------------------------------------------------------------- /src/devices/uniel_device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "serial_config.h" 9 | #include "serial_device.h" 10 | 11 | class TUnielDevice: public TSerialDevice, public TUInt32SlaveId 12 | { 13 | public: 14 | enum RegisterType 15 | { 16 | REG_RELAY = 0, 17 | REG_INPUT, 18 | REG_PARAM, 19 | REG_BRIGHTNESS 20 | }; 21 | 22 | TUnielDevice(PDeviceConfig config, PProtocol protocol); 23 | 24 | static void Register(TSerialDeviceFactory& factory); 25 | 26 | TRegisterValue ReadRegisterImpl(TPort& port, const TRegisterConfig& reg) override; 27 | 28 | protected: 29 | void WriteRegisterImpl(TPort& port, const TRegisterConfig& reg, const TRegisterValue& regValue) override; 30 | 31 | private: 32 | void WriteCommand(TPort& port, uint8_t cmd, uint8_t mod, uint8_t b1, uint8_t b2, uint8_t b3); 33 | void ReadResponse(TPort& port, uint8_t cmd, uint8_t* response); 34 | }; 35 | 36 | typedef std::shared_ptr PUnielDevice; 37 | -------------------------------------------------------------------------------- /src/files_watcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class TFilesWatcher 9 | { 10 | public: 11 | enum class TEvent 12 | { 13 | CloseWrite, 14 | Delete 15 | }; 16 | 17 | typedef std::function TCallback; 18 | 19 | TFilesWatcher(const std::vector& paths, TCallback callback); 20 | ~TFilesWatcher(); 21 | 22 | private: 23 | TCallback Callback; 24 | std::atomic Running; 25 | std::thread WatcherThread; 26 | }; 27 | -------------------------------------------------------------------------------- /src/json_common.cpp: -------------------------------------------------------------------------------- 1 | #include "json_common.h" 2 | 3 | Json::Value& MakeArray(const std::string& key, Json::Value& node) 4 | { 5 | return (node[key] = Json::Value(Json::arrayValue)); 6 | } 7 | 8 | Json::Value& Append(Json::Value& array) 9 | { 10 | return array.append(Json::Value()); 11 | } 12 | 13 | Json::Value MakeObject(const std::string& key, const std::string& value) 14 | { 15 | Json::Value res; 16 | res[key] = value; 17 | return res; 18 | } 19 | 20 | Json::Value MakeSingleValueProperty(const std::string& value) 21 | { 22 | Json::Value res; 23 | res["type"] = "string"; 24 | MakeArray("enum", res).append(value); 25 | return res; 26 | } 27 | 28 | std::unordered_map GetTranslations(const std::string& key, const Json::Value& schema) 29 | { 30 | std::unordered_map res; 31 | if (key.empty()) { 32 | return res; 33 | } 34 | if (schema.isMember("translations")) { 35 | const auto& translations = schema["translations"]; 36 | for (Json::ValueConstIterator it = translations.begin(); it != translations.end(); ++it) { 37 | std::string tr = it->get(key, std::string()).asString(); 38 | if (!tr.empty()) { 39 | res.emplace(it.name(), tr); 40 | } 41 | } 42 | } 43 | if (!res.count("en")) { 44 | res.emplace("en", key); 45 | } 46 | return res; 47 | } 48 | -------------------------------------------------------------------------------- /src/json_common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // key : [ ] 5 | Json::Value& MakeArray(const std::string& key, Json::Value& node); 6 | 7 | // { 8 | // "key": "value" 9 | // } 10 | Json::Value MakeObject(const std::string& key, const std::string& value); 11 | 12 | //! Appends an empty Json::Value object to array an returns reference to the object 13 | Json::Value& Append(Json::Value& array); 14 | 15 | // { 16 | // "type": "string", 17 | // "enum": [ value ] 18 | // } 19 | Json::Value MakeSingleValueProperty(const std::string& value); 20 | 21 | std::unordered_map GetTranslations(const std::string& key, const Json::Value& deviceTemplate); 22 | -------------------------------------------------------------------------------- /src/log.cpp: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | 3 | // clang-format off 4 | WBMQTT::TLogger Error("ERROR: ", WBMQTT::TLogger::StdErr, WBMQTT::TLogger::RED); 5 | WBMQTT::TLogger Warn ("WARNING: ", WBMQTT::TLogger::StdErr, WBMQTT::TLogger::YELLOW); 6 | WBMQTT::TLogger Info ("INFO: ", WBMQTT::TLogger::StdErr, WBMQTT::TLogger::GREY); 7 | WBMQTT::TLogger Debug("DEBUG: ", WBMQTT::TLogger::StdErr, WBMQTT::TLogger::WHITE, false); 8 | // clang-format on 9 | 10 | TLoggerWithTimeout::TLoggerWithTimeout(const std::chrono::milliseconds& notificationInterval, const std::string& prefix) 11 | : NotificationInterval(notificationInterval), 12 | Prefix(prefix) 13 | {} 14 | 15 | void TLoggerWithTimeout::Log(const std::string& msg, WBMQTT::TLogger& debugLogger, WBMQTT::TLogger& errorLogger) 16 | { 17 | auto currentTime = std::chrono::steady_clock::now(); 18 | auto delta = std::chrono::duration_cast(currentTime - LastErrorNotificationTime); 19 | if (delta < NotificationInterval) { 20 | debugLogger.Log() << Prefix << msg; 21 | } else { 22 | errorLogger.Log() << Prefix << msg; 23 | LastErrorNotificationTime = currentTime; 24 | } 25 | } 26 | 27 | void TLoggerWithTimeout::DropTimeout() 28 | { 29 | LastErrorNotificationTime = std::chrono::steady_clock::time_point(); 30 | } 31 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | extern WBMQTT::TLogger Error; 7 | extern WBMQTT::TLogger Warn; 8 | extern WBMQTT::TLogger Info; 9 | extern WBMQTT::TLogger Debug; 10 | 11 | class TLoggerWithTimeout 12 | { 13 | std::chrono::steady_clock::time_point LastErrorNotificationTime; 14 | std::chrono::milliseconds NotificationInterval; 15 | std::string Prefix; 16 | 17 | public: 18 | TLoggerWithTimeout(const std::chrono::milliseconds& notificationInterval, const std::string& prefix); 19 | 20 | void Log(const std::string& msg, WBMQTT::TLogger& debugLogger, WBMQTT::TLogger& errorLogger); 21 | 22 | void DropTimeout(); 23 | }; 24 | -------------------------------------------------------------------------------- /src/port/tcp_port.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "file_descriptor_port.h" 4 | #include "tcp_port_settings.h" 5 | 6 | class TTcpPort final: public TFileDescriptorPort 7 | { 8 | using Base = TFileDescriptorPort; 9 | 10 | public: 11 | TTcpPort(const TTcpPortSettings& settings); 12 | ~TTcpPort() = default; 13 | 14 | void Open() override; 15 | void WriteBytes(const uint8_t* buf, int count) override; 16 | uint8_t ReadByte(const std::chrono::microseconds& timeout) override; 17 | TReadFrameResult ReadFrame(uint8_t* buf, 18 | size_t count, 19 | const std::chrono::microseconds& responseTimeout, 20 | const std::chrono::microseconds& frameTimeout, 21 | TFrameCompletePred frame_complete = 0) override; 22 | 23 | std::string GetDescription(bool verbose = true) const override; 24 | 25 | std::chrono::microseconds GetSendTimeBytes(double bytesNumber) const override; 26 | std::chrono::microseconds GetSendTimeBits(size_t bitsNumber) const override; 27 | 28 | private: 29 | void OnReadyEmptyFd() override; 30 | 31 | TTcpPortSettings Settings; 32 | }; 33 | -------------------------------------------------------------------------------- /src/port/tcp_port_settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct TTcpPortSettings 7 | { 8 | TTcpPortSettings(const std::string& address = "localhost", uint16_t port = 0): Address(address), Port(port) 9 | {} 10 | 11 | std::string ToString() const 12 | { 13 | std::ostringstream ss; 14 | ss << "<" << Address << ":" << Port << ">"; 15 | return ss.str(); 16 | } 17 | 18 | std::string Address; 19 | uint16_t Port; 20 | }; 21 | -------------------------------------------------------------------------------- /src/register_handler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "bcd_utils.h" 3 | #include "register.h" 4 | #include "serial_device.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using WBMQTT::StringFormat; 12 | 13 | class TRegisterHandler 14 | { 15 | public: 16 | TRegisterHandler(PRegister reg); 17 | 18 | PRegister Register() const; 19 | 20 | bool NeedToFlush(); 21 | 22 | /** 23 | * @brief Write pending register value. NeedToFlush must be checked before call. 24 | */ 25 | void Flush(TPort& port); 26 | 27 | void SetTextValue(const std::string& v); 28 | 29 | private: 30 | TRegisterValue ValueToSet{0}; 31 | PRegister Reg; 32 | volatile bool Dirty = false; 33 | std::mutex SetValueMutex; 34 | bool WriteFail; 35 | std::chrono::steady_clock::time_point WriteFirstTryTime; 36 | 37 | void HandleWriteErrorNoRetry(const TRegisterValue& tempValue, const char* msg); 38 | void HandleWriteErrorRetryWrite(const TRegisterValue& tempValue, const char* msg); 39 | }; 40 | 41 | typedef std::shared_ptr PRegisterHandler; 42 | -------------------------------------------------------------------------------- /src/rpc/rpc_config.cpp: -------------------------------------------------------------------------------- 1 | #include "rpc_config.h" 2 | #include 3 | 4 | void TRPCConfig::AddSerialPort(const TSerialPortSettings& settings) 5 | { 6 | Json::Value item; 7 | item["path"] = settings.Device; 8 | item["baud_rate"] = settings.BaudRate; 9 | item["data_bits"] = settings.DataBits; 10 | item["parity"] = std::string(1, settings.Parity); 11 | item["stop_bits"] = settings.StopBits; 12 | PortConfigs.append(std::move(item)); 13 | } 14 | 15 | void TRPCConfig::AddTCPPort(const TTcpPortSettings& settings) 16 | { 17 | Json::Value item; 18 | item["address"] = settings.Address; 19 | item["port"] = settings.Port; 20 | PortConfigs.append(std::move(item)); 21 | } 22 | 23 | void TRPCConfig::AddModbusTCPPort(const TTcpPortSettings& settings) 24 | { 25 | Json::Value item; 26 | item["address"] = settings.Address; 27 | item["port"] = settings.Port; 28 | item["mode"] = "modbus-tcp"; 29 | PortConfigs.append(std::move(item)); 30 | } 31 | 32 | Json::Value TRPCConfig::GetPortConfigs() const 33 | { 34 | return PortConfigs; 35 | } 36 | -------------------------------------------------------------------------------- /src/rpc/rpc_config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "port/serial_port_settings.h" 8 | #include "port/tcp_port_settings.h" 9 | 10 | class TRPCConfig 11 | { 12 | public: 13 | void AddSerialPort(const TSerialPortSettings& settings); 14 | void AddTCPPort(const TTcpPortSettings& settings); 15 | void AddModbusTCPPort(const TTcpPortSettings& settings); 16 | Json::Value GetPortConfigs() const; 17 | 18 | private: 19 | Json::Value PortConfigs{Json::arrayValue}; 20 | }; 21 | 22 | typedef std::shared_ptr PRPCConfig; 23 | -------------------------------------------------------------------------------- /src/rpc/rpc_config_handler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "confed_device_schemas_map.h" 6 | #include "confed_protocol_schemas_map.h" 7 | #include "serial_config.h" 8 | class TRPCConfigHandler 9 | { 10 | public: 11 | TRPCConfigHandler(const std::string& configPath, 12 | const Json::Value& portsSchema, 13 | PTemplateMap templates, 14 | TDevicesConfedSchemasMap& deviceConfedSchemas, 15 | TProtocolConfedSchemasMap& protocolConfedSchemas, 16 | const Json::Value& groupTranslations, 17 | WBMQTT::PMqttRpcServer rpcServer); 18 | 19 | private: 20 | std::string ConfigPath; 21 | const Json::Value& PortsSchema; 22 | PTemplateMap Templates; 23 | TDevicesConfedSchemasMap& DeviceConfedSchemas; 24 | TProtocolConfedSchemasMap& ProtocolConfedSchemas; 25 | Json::Value GroupTranslations; 26 | 27 | Json::Value LoadConfig(const Json::Value& request); 28 | Json::Value GetDeviceTypes(const Json::Value& request); 29 | Json::Value GetSchema(const Json::Value& request); 30 | }; 31 | 32 | typedef std::shared_ptr PRPCConfigHandler; 33 | -------------------------------------------------------------------------------- /src/rpc/rpc_device_probe_task.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "serial_client.h" 6 | 7 | class TRPCDeviceProbeSerialClientTask: public ISerialClientTask 8 | { 9 | public: 10 | TRPCDeviceProbeSerialClientTask(const Json::Value& request, 11 | WBMQTT::TMqttRpcServer::TResultCallback onResult, 12 | WBMQTT::TMqttRpcServer::TErrorCallback onError); 13 | 14 | ISerialClientTask::TRunResult Run(PFeaturePort port, 15 | TSerialClientDeviceAccessHandler& lastAccessedDevice, 16 | const std::list& polledDevices) override; 17 | 18 | private: 19 | TSerialPortConnectionSettings SerialPortSettings; 20 | std::chrono::steady_clock::time_point ExpireTime; 21 | uint8_t SlaveId; 22 | std::unique_ptr ModbusTraits; 23 | 24 | WBMQTT::TMqttRpcServer::TResultCallback OnResult; 25 | WBMQTT::TMqttRpcServer::TErrorCallback OnError; 26 | }; 27 | -------------------------------------------------------------------------------- /src/rpc/rpc_exception.cpp: -------------------------------------------------------------------------------- 1 | #include "rpc_exception.h" 2 | #include "log.h" 3 | 4 | #define LOG(logger) ::logger.Log() << "[RPC] " 5 | 6 | TRPCException::TRPCException(const std::string& message, TRPCResultCode resultCode) 7 | : std::runtime_error(message), 8 | ResultCode(resultCode) 9 | {} 10 | 11 | TRPCResultCode TRPCException::GetResultCode() const 12 | { 13 | return ResultCode; 14 | } 15 | 16 | std::string TRPCException::GetResultMessage() const 17 | { 18 | return this->what(); 19 | } 20 | 21 | void ProcessException(const TRPCException& e, WBMQTT::TMqttRpcServer::TErrorCallback onError) 22 | { 23 | if (e.GetResultCode() == TRPCResultCode::RPC_WRONG_IO) { 24 | // Too many "request timed out" errors while scanning ports 25 | LOG(Debug) << e.GetResultMessage(); 26 | } else { 27 | LOG(Warn) << e.GetResultMessage(); 28 | } 29 | switch (e.GetResultCode()) { 30 | case TRPCResultCode::RPC_WRONG_TIMEOUT: { 31 | onError(WBMQTT::E_RPC_REQUEST_TIMEOUT, e.GetResultMessage()); 32 | break; 33 | } 34 | default: { 35 | onError(WBMQTT::E_RPC_SERVER_ERROR, e.GetResultMessage()); 36 | break; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/rpc/rpc_exception.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | // RPC Request execution result code 7 | enum class TRPCResultCode 8 | { 9 | // No errors 10 | RPC_OK = 0, 11 | // Wrong parameters value 12 | RPC_WRONG_PARAM_VALUE = -1, 13 | // Requested port was not found 14 | RPC_WRONG_PORT = -2, 15 | // Unsuccessful port IO 16 | RPC_WRONG_IO = -3, 17 | // RPC request handling timeout 18 | RPC_WRONG_TIMEOUT = -4 19 | }; 20 | 21 | class TRPCException: public std::runtime_error 22 | { 23 | public: 24 | TRPCException(const std::string& message, TRPCResultCode resultCode); 25 | TRPCResultCode GetResultCode() const; 26 | std::string GetResultMessage() const; 27 | 28 | private: 29 | TRPCResultCode ResultCode; 30 | }; 31 | 32 | void ProcessException(const TRPCException& e, WBMQTT::TMqttRpcServer::TErrorCallback onError); 33 | -------------------------------------------------------------------------------- /src/rpc/rpc_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include "rpc_helpers.h" 2 | #include "log.h" 3 | #include "rpc_exception.h" 4 | 5 | #define LOG(logger) ::logger.Log() << "[RPC] " 6 | 7 | TSerialPortConnectionSettings ParseRPCSerialPortSettings(const Json::Value& request) 8 | { 9 | TSerialPortConnectionSettings res; 10 | WBMQTT::JSON::Get(request, "baud_rate", res.BaudRate); 11 | if (request.isMember("parity")) { 12 | res.Parity = request["parity"].asCString()[0]; 13 | } 14 | WBMQTT::JSON::Get(request, "data_bits", res.DataBits); 15 | WBMQTT::JSON::Get(request, "stop_bits", res.StopBits); 16 | return res; 17 | } 18 | 19 | void ValidateRPCRequest(const Json::Value& request, const Json::Value& schema) 20 | { 21 | try { 22 | WBMQTT::JSON::Validate(request, schema); 23 | } catch (const std::runtime_error& e) { 24 | throw TRPCException(e.what(), TRPCResultCode::RPC_WRONG_PARAM_VALUE); 25 | } 26 | } 27 | 28 | Json::Value LoadRPCRequestSchema(const std::string& schemaFilePath, const std::string& rpcName) 29 | { 30 | try { 31 | return WBMQTT::JSON::Parse(schemaFilePath); 32 | } catch (const std::runtime_error& e) { 33 | LOG(Error) << "RPC " + rpcName + " request schema reading error: " << e.what(); 34 | throw; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/rpc/rpc_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "port/serial_port_settings.h" 6 | 7 | TSerialPortConnectionSettings ParseRPCSerialPortSettings(const Json::Value& request); 8 | 9 | /** 10 | * @brief Validates an RPC request against a given JSON schema. 11 | * 12 | * @param request The JSON object representing the RPC request to be validated. 13 | * @param schema The JSON object representing the schema to validate the request against. 14 | * 15 | * @throws TRPCException with TRPCResultCode::RPC_WRONG_PARAM_VALUE code, if the request does not conform to the schema. 16 | */ 17 | void ValidateRPCRequest(const Json::Value& request, const Json::Value& schema); 18 | 19 | /** 20 | * @brief Loads the JSON schema for an RPC request from a specified file. 21 | * Prints a message to the log if the file cannot be read and throws an exception. 22 | * 23 | * @param schemaFilePath The path to the JSON schema file. 24 | * @param rpcName The name of the RPC for which the schema is to be loaded. Example: "port/Load". 25 | * @return A Json::Value object containing the schema. 26 | * @throws std::runtime_error If the schema file cannot be read. 27 | */ 28 | Json::Value LoadRPCRequestSchema(const std::string& schemaFilePath, const std::string& rpcName); 29 | -------------------------------------------------------------------------------- /src/rpc/rpc_port_driver_list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "rpc_config.h" 4 | #include "rpc_exception.h" 5 | #include "serial_driver.h" 6 | 7 | class TSerialClientTaskExecutor: public util::TNonCopyable 8 | { 9 | public: 10 | TSerialClientTaskExecutor(PFeaturePort port); 11 | ~TSerialClientTaskExecutor(); 12 | 13 | void AddTask(PSerialClientTask task); 14 | 15 | PFeaturePort GetPort() const; 16 | 17 | bool IsIdle() const; 18 | 19 | private: 20 | PFeaturePort Port; 21 | 22 | mutable std::mutex Mutex; 23 | std::condition_variable TasksCv; 24 | std::vector Tasks; 25 | 26 | std::thread Thread; 27 | std::atomic Running; 28 | bool Idle; 29 | }; 30 | 31 | typedef std::shared_ptr PSerialClientTaskExecutor; 32 | 33 | struct TSerialClientParams 34 | { 35 | PSerialClient SerialClient; 36 | PSerialDevice Device; 37 | }; 38 | 39 | class TSerialClientTaskRunner 40 | { 41 | public: 42 | TSerialClientTaskRunner(PMQTTSerialDriver serialDriver); 43 | 44 | TSerialClientParams GetSerialClientParams(const Json::Value& request); 45 | void RunTask(const Json::Value& request, PSerialClientTask task); 46 | 47 | private: 48 | PMQTTSerialDriver SerialDriver; 49 | 50 | std::vector TaskExecutors; 51 | std::mutex TaskExecutorsMutex; 52 | 53 | void RemoveUnusedExecutors(); 54 | }; 55 | -------------------------------------------------------------------------------- /src/rpc/rpc_port_load_raw_serial_client_task.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "rpc_port_load_request.h" 7 | #include "serial_client.h" 8 | 9 | class TRPCPortLoadRawRequest: public TRPCPortLoadRequest 10 | { 11 | public: 12 | size_t ResponseSize; 13 | }; 14 | 15 | typedef std::shared_ptr PRPCPortLoadRawRequest; 16 | 17 | class TRPCPortLoadRawSerialClientTask: public ISerialClientTask 18 | { 19 | public: 20 | TRPCPortLoadRawSerialClientTask(const Json::Value& request, 21 | WBMQTT::TMqttRpcServer::TResultCallback onResult, 22 | WBMQTT::TMqttRpcServer::TErrorCallback onError); 23 | 24 | ISerialClientTask::TRunResult Run(PFeaturePort port, 25 | TSerialClientDeviceAccessHandler& lastAccessedDevice, 26 | const std::list& polledDevices) override; 27 | 28 | private: 29 | PRPCPortLoadRawRequest Request; 30 | std::chrono::steady_clock::time_point ExpireTime; 31 | }; 32 | 33 | typedef std::shared_ptr PRPCPortLoadRawSerialClientTask; 34 | -------------------------------------------------------------------------------- /src/rpc/rpc_port_load_request.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "port/serial_port_settings.h" 7 | #include "rpc_port_handler.h" 8 | #include "serial_device.h" 9 | 10 | enum class TRPCMessageFormat 11 | { 12 | RPC_MESSAGE_FORMAT_HEX, 13 | RPC_MESSAGE_FORMAT_STR 14 | }; 15 | 16 | class TRPCPortLoadRequest 17 | { 18 | public: 19 | std::vector Message; 20 | std::chrono::milliseconds ResponseTimeout = DEFAULT_RESPONSE_TIMEOUT; 21 | std::chrono::milliseconds FrameTimeout = DefaultFrameTimeout; 22 | std::chrono::milliseconds TotalTimeout = DefaultRPCTotalTimeout; 23 | TRPCMessageFormat Format; 24 | 25 | TSerialPortConnectionSettings SerialPortSettings; 26 | 27 | WBMQTT::TMqttRpcServer::TResultCallback OnResult = nullptr; 28 | WBMQTT::TMqttRpcServer::TErrorCallback OnError = nullptr; 29 | }; 30 | 31 | typedef std::shared_ptr PRPCPortLoadRequest; 32 | 33 | void ParseRPCPortLoadRequest(const Json::Value& data, TRPCPortLoadRequest& request); 34 | std::string FormatResponse(const std::vector& response, TRPCMessageFormat format); 35 | std::vector HexStringToByteVector(const std::string& hexString); 36 | -------------------------------------------------------------------------------- /src/running_average.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | template class TRunningAverage 6 | { 7 | ValueType Average; 8 | 9 | public: 10 | TRunningAverage(const ValueType& initialValue): Average(initialValue) 11 | {} 12 | 13 | const ValueType& GetValue() const 14 | { 15 | return Average; 16 | } 17 | 18 | void AddValue(const ValueType& value) 19 | { 20 | Average = ((WindowSize - 1) * Average + value) / WindowSize; 21 | } 22 | }; 23 | 24 | template class TRunningAverage 25 | { 26 | public: 27 | TRunningAverage() 28 | {} 29 | }; 30 | -------------------------------------------------------------------------------- /src/serial_client_device_access_handler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serial_client_events_reader.h" 4 | #include "serial_device.h" 5 | 6 | class TSerialClientDeviceAccessHandler 7 | { 8 | public: 9 | TSerialClientDeviceAccessHandler(PSerialClientEventsReader eventsReader); 10 | bool PrepareToAccess(TFeaturePort& port, PSerialDevice dev); 11 | 12 | private: 13 | PSerialDevice LastAccessedDevice; 14 | PSerialClientEventsReader EventsReader; 15 | }; 16 | -------------------------------------------------------------------------------- /src/serial_driver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "serial_port_driver.h" 4 | 5 | class TMQTTSerialDriver 6 | { 7 | public: 8 | TMQTTSerialDriver(WBMQTT::PDeviceDriver mqtt_driver, PHandlerConfig handler_config); 9 | void LoopOnce(); 10 | void ClearDevices(); 11 | 12 | void Start(); 13 | void Stop(); 14 | 15 | std::vector GetPortDrivers(); 16 | 17 | private: 18 | std::vector PortDrivers; 19 | std::vector PortLoops; 20 | std::mutex ActiveMutex; 21 | bool Active; 22 | }; 23 | 24 | typedef std::shared_ptr PMQTTSerialDriver; 25 | -------------------------------------------------------------------------------- /src/serial_exc.cpp: -------------------------------------------------------------------------------- 1 | #include "serial_exc.h" 2 | #include 3 | 4 | std::string FormatErrno(int errnoValue) 5 | { 6 | return std::string(strerror(errnoValue)) + " (" + std::to_string(errnoValue) + ")"; 7 | } 8 | 9 | TSerialDeviceException::TSerialDeviceException(const std::string& message) 10 | : std::runtime_error("Serial protocol error: " + message) 11 | {} 12 | 13 | TSerialDeviceErrnoException::TSerialDeviceErrnoException(const std::string& message, int errnoValue) 14 | : TSerialDeviceException(message + FormatErrno(errnoValue)), 15 | ErrnoValue(errnoValue) 16 | {} 17 | 18 | int TSerialDeviceErrnoException::GetErrnoValue() const 19 | { 20 | return ErrnoValue; 21 | } 22 | 23 | TSerialDeviceTransientErrorException::TSerialDeviceTransientErrorException(const std::string& message) 24 | : TSerialDeviceException(message) 25 | {} 26 | 27 | TSerialDevicePermanentRegisterException::TSerialDevicePermanentRegisterException(const std::string& message) 28 | : TSerialDeviceException(message) 29 | {} 30 | 31 | TSerialDeviceInternalErrorException::TSerialDeviceInternalErrorException(const std::string& message) 32 | : TSerialDeviceTransientErrorException(message) 33 | {} 34 | 35 | TResponseTimeoutException::TResponseTimeoutException(): TSerialDeviceTransientErrorException("request timed out") 36 | {} 37 | -------------------------------------------------------------------------------- /src/wb_registers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "register.h" 4 | 5 | namespace WbRegisters 6 | { 7 | const std::string BAUD_RATE_REGISTER_NAME = "baud_rate"; 8 | const std::string PARITY_REGISTER_NAME = "parity"; 9 | const std::string STOP_BITS_REGISTER_NAME = "stop_bits"; 10 | const std::string CONTINUOUS_READ_REGISTER_NAME = "continuous_read"; 11 | const std::string SLAVE_ID_REGISTER_NAME = "slave_id"; 12 | const std::string DEVICE_MODEL_REGISTER_NAME = "device_model"; 13 | const std::string DEVICE_MODEL_EX_REGISTER_NAME = "device_model_ex"; 14 | const std::string FW_SIGNATURE_REGISTER_NAME = "fw_signature"; 15 | const std::string FW_VERSION_REGISTER_NAME = "fw_version"; 16 | const std::string SN_REGISTER_NAME = "sn"; 17 | 18 | const uint16_t COUNTINUOUS_READ_DISABLED = 0; 19 | const uint16_t COUNTINUOUS_READ_ENABLED_TEMPORARY = 1; 20 | const uint16_t COUNTINUOUS_READ_ENABLED = 2; 21 | 22 | PRegisterConfig GetRegisterConfig(const std::string& name); 23 | 24 | } // namespace 25 | -------------------------------------------------------------------------------- /src/write_channel_serial_client_task.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "register_handler.h" 4 | #include "serial_client.h" 5 | 6 | class TWriteChannelSerialClientTask: public ISerialClientTask 7 | { 8 | 9 | public: 10 | typedef std::function TRegisterCallback; 11 | 12 | TWriteChannelSerialClientTask(PRegisterHandler handler, 13 | TRegisterCallback readCallback, 14 | TRegisterCallback errorCallback); 15 | 16 | ~TWriteChannelSerialClientTask() = default; 17 | 18 | ISerialClientTask::TRunResult Run(PFeaturePort port, 19 | TSerialClientDeviceAccessHandler& lastAccessedDevice, 20 | const std::list& polledDevices) override; 21 | 22 | private: 23 | PRegisterHandler Handler; 24 | TRegisterCallback ReadCallback; 25 | TRegisterCallback ErrorCallback; 26 | }; 27 | -------------------------------------------------------------------------------- /templates/config-bac-6000-series.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "BAC-6000 Series", 3 | "group": "g-thermostat", 4 | "device": { 5 | "name": "BAC-6000 Series", 6 | "id": "bac-6000-series", 7 | "deprecated": true, 8 | "channels": [ 9 | { 10 | "name": "Lock buttons", 11 | "reg_type": "holding", 12 | "address": "5", 13 | "type": "switch", 14 | "format": "s16" 15 | }, 16 | { 17 | "name": "Room temperature", 18 | "reg_type": "holding", 19 | "address": "3", 20 | "type": "temperature", 21 | "format": "s16", 22 | "scale": 0.5, 23 | "readonly": true 24 | }, 25 | { 26 | "name": "Fan Speed", 27 | "reg_type": "holding", 28 | "address": "1", 29 | "type": "range", 30 | "format": "s16", 31 | "max": 3 32 | }, 33 | { 34 | "name": "Setting Mode", 35 | "reg_type": "holding", 36 | "address": "2", 37 | "type": "range", 38 | "format": "s16", 39 | "max": 2 40 | }, 41 | { 42 | "name": "Setting temperature", 43 | "reg_type": "holding", 44 | "address": "4", 45 | "type": "range", 46 | "format": "s16", 47 | "scale": 0.5, 48 | "min": 10, 49 | "max": 30 50 | } 51 | ] 52 | } 53 | } -------------------------------------------------------------------------------- /templates/config-ddl04r.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "DDL04R", 3 | "group": "g-dimmer", 4 | "device": { 5 | "name": "DDL04R", 6 | "id": "ddl04r", 7 | "max_read_registers": 4, 8 | "frame_timeout_ms": 0, 9 | "channels": [ 10 | { 11 | "name": "Channel 1", 12 | "reg_type": "holding", 13 | "address": 5, 14 | "type": "range", 15 | "max": 1023 16 | }, 17 | { 18 | "name": "Channel 2", 19 | "reg_type": "holding", 20 | "address": 6, 21 | "type": "range", 22 | "max": 1023 23 | }, 24 | { 25 | "name": "Channel 3", 26 | "reg_type": "holding", 27 | "address": 7, 28 | "type": "range", 29 | "max": 1023 30 | }, 31 | { 32 | "name": "Channel 4", 33 | "reg_type": "holding", 34 | "address": 8, 35 | "type": "range", 36 | "max": 1023 37 | } 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /templates/config-ddl24.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "DDL24", 3 | "group": "g-dimmer", 4 | "device": { 5 | "name": "DDL24", 6 | "id": "ddl24", 7 | "frame_timeout_ms": 0, 8 | "channels": [ 9 | { 10 | "name": "RGB", 11 | "type": "rgb", 12 | "consists_of": [ 13 | { 14 | "reg_type": "holding", 15 | "address": 4 16 | }, 17 | { 18 | "reg_type": "holding", 19 | "address": 5 20 | }, 21 | { 22 | "reg_type": "holding", 23 | "address": 6 24 | } 25 | ] 26 | }, 27 | { 28 | "name": "White", 29 | "reg_type": "holding", 30 | "address": 7, 31 | "type": "dimmer", 32 | "max": "0xff" 33 | }, 34 | { 35 | "name": "RGB_All", 36 | "reg_type": "holding", 37 | "address": 8, 38 | "type": "range", 39 | "max": 100 40 | }, 41 | { 42 | "name": "White1", 43 | "reg_type": "holding", 44 | "address": 9, 45 | "type": "range", 46 | "max": 100 47 | }, 48 | { 49 | "name": "Voltage", 50 | "reg_type": "holding", 51 | "address": 18, 52 | "type": "voltage" 53 | } 54 | ] 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /templates/config-ivtm-7m-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "IVTM-7M-3", 3 | "group": "g-climate-sensor", 4 | "device": { 5 | "name": "IVTM-7M-3", 6 | "id": "ivtm7m3", 7 | "protocol": "ivtm", 8 | "response_timeout_ms": 300, 9 | "frame_timeout_ms": 0, 10 | "channels": [ 11 | { 12 | "name": "Temperature", 13 | "reg_type": "default", 14 | "address": "0x00", 15 | "format": "float", 16 | "type": "temperature" 17 | }, 18 | { 19 | "name": "Humidity", 20 | "reg_type": "default", 21 | "address": "0x04", 22 | "format": "float", 23 | "type": "rel_humidity" 24 | } 25 | ] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /templates/config-lc103.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type" : "LC-103", 3 | "group": "g-relay", 4 | "device" : { 5 | "name": "LC-103", 6 | "id": "lc103", 7 | "frame_timeout_ms": 0, 8 | "channels": [ 9 | { 10 | "name": "Relay 1", 11 | "reg_type": "coil", 12 | "address": "0x00", 13 | "type": "switch" 14 | }, 15 | { 16 | "name": "Relay 2", 17 | "reg_type": "coil", 18 | "address": "0x01", 19 | "type": "switch" 20 | }, 21 | { 22 | "name": "Relay 3", 23 | "reg_type": "coil", 24 | "address": "0x02", 25 | "type": "switch" 26 | }, 27 | { 28 | "name": "Switch AC In", 29 | "reg_type": "discrete", 30 | "address": "0x00" 31 | } 32 | ] 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /templates/config-msu21.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "MSU21", 3 | "group": "g-climate-sensor", 4 | "device": { 5 | "name": "MSU21", 6 | "id": "msu21", 7 | "frame_timeout_ms": 0, 8 | "setup": [ 9 | { 10 | "title": "Input 0 type", 11 | "address": 1, 12 | "value": 2 13 | }, 14 | { 15 | "title": "Input 0 module", 16 | "address": "0x03", 17 | "value": "6" 18 | } 19 | ], 20 | "channels": [ 21 | { 22 | "name": "Temperature", 23 | "reg_type": "input", 24 | "address": 0, 25 | "type": "temperature", 26 | "format": "s8" 27 | } 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /templates/config-msu24.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "MSU24", 3 | "group": "g-climate-sensor", 4 | "device": { 5 | "name": "MSU24", 6 | "id": "msu24", 7 | "frame_timeout_ms": 0, 8 | "channels": [ 9 | { 10 | "name": "Illuminance", 11 | "reg_type": "input", 12 | "address": 0, 13 | "type": "lux" 14 | }, 15 | { 16 | "name": "Temp 1", 17 | "reg_type": "input", 18 | "address": 1, 19 | "type": "temperature", 20 | "format": "s8" 21 | } 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /templates/config-msu34.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "MSU34", 3 | "group": "g-climate-sensor", 4 | "device": { 5 | "name": "MSU34+TLP", 6 | "id": "msu34tlp", 7 | "frame_timeout_ms": 0, 8 | "channels": [ 9 | { 10 | "name": "Temp 1", 11 | "reg_type": "input", 12 | "address": 0, 13 | "type": "temperature", 14 | "format": "s8" 15 | }, 16 | { 17 | "name": "Illuminance", 18 | "reg_type": "input", 19 | "address": 1, 20 | "type": "lux" 21 | }, 22 | { 23 | "name": "Pressure", 24 | "reg_type": "input", 25 | "address": 2, 26 | "type": "pressure", 27 | "scale": 0.075 28 | }, 29 | { 30 | "name": "Temp 2", 31 | "reg_type": "input", 32 | "address": 3, 33 | "type": "temperature", 34 | "format": "s8" 35 | } 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /templates/config-msu34tlhp.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "MSU34TLHP", 3 | "group": "g-climate-sensor", 4 | "device": { 5 | "name": "MSU34+TLHP", 6 | "id": "msu34tlhp", 7 | "frame_timeout_ms": 0, 8 | "channels": [ 9 | { 10 | "name": "Illuminance", 11 | "reg_type": "input", 12 | "address": 0, 13 | "type": "lux" 14 | }, 15 | { 16 | "name": "Temp 1", 17 | "reg_type": "input", 18 | "address": 1, 19 | "type": "temperature", 20 | "format": "s8" 21 | }, 22 | { 23 | "name": "Pressure", 24 | "reg_type": "input", 25 | "address": 2, 26 | "type": "pressure", 27 | "scale": 0.075 28 | }, 29 | { 30 | "name": "Humidity", 31 | "reg_type": "input", 32 | "address": 3, 33 | "type": "rel_humidity", 34 | "format": "s8" 35 | } 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /templates/config-oni-plc-w-acs-0800-imp.json.jinja: -------------------------------------------------------------------------------- 1 | {% with title_en = "PLC-W-ACS-0800-IMP (8-channel pulse counter)", 2 | title_ru = "PLC-W-ACS-0800-IMP (8-канальный модуль счетных входов)", 3 | device_type = "tpl1_oni_plc_w_acs_0800_imp", 4 | group = "g-oni", 5 | device_name = "PLC-W-ACS-0800-IMP", 6 | device_id = "oni-plc-w-acs-0800-imp", 7 | has_signature = false %} 8 | {% include "config-wb-mcm8.json.jinja" %} 9 | {% endwith %} 10 | -------------------------------------------------------------------------------- /templates/config-oni-plc-w-ema-0304.json.jinja: -------------------------------------------------------------------------------- 1 | {% with title_en = "PLC-W-EMA-0304 (4-channel analog output module)", 2 | title_ru = "PLC-W-EMA-0304 (4-канальный модуль аналогового вывода)", 3 | device_type = "tpl1_oni_plc_w_ema_0304", 4 | group = "g-oni", 5 | device_name = "PLC-W-EMA-0304", 6 | device_id = "oni-plc-w-ema-0304", 7 | has_signature = false %} 8 | {% include "config-wb-mao4.json.jinja" %} 9 | {% endwith %} 10 | -------------------------------------------------------------------------------- /templates/config-oni-plc-w-ema-06u00.json.jinja: -------------------------------------------------------------------------------- 1 | {% with title_en = "PLC-W-EMA-06U00 (6-channel analog input module)", 2 | title_ru = "PLC-W-EMA-06U00 (6-канальный модуль аналоговых входов)", 3 | device_type = "tpl1_oni_plc_w_ema_06U00", 4 | group = "g-oni", 5 | device_name = "PLC-W-EMA-06U00", 6 | device_id = "oni-plc-w-ema-06u00", 7 | has_signature = false %} 8 | {% include "config-wb-mai6.json.jinja" %} 9 | {% endwith %} 10 | -------------------------------------------------------------------------------- /templates/config-oni-plc-w-emd-0706.json.jinja: -------------------------------------------------------------------------------- 1 | {% with title_en = "PLC-W-EMD-0706 (6-channel relay)", 2 | title_ru = "PLC-W-EMD-0706 (6-канальный модуль реле)", 3 | device_type = "tpl1_oni_plc_w_emd_0706", 4 | group = "g-oni", 5 | device_name = "PLC-W-EMD-0706", 6 | device_id = "oni-plc-w-emd-0706", 7 | has_signature = false %} 8 | {% include "config-wb-mr6c.json.jinja" %} 9 | {% endwith %} 10 | -------------------------------------------------------------------------------- /templates/config-pulsar-m-water.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "pulsar-m-water", 3 | "title": "Pulsar-M Water Meter", 4 | "group": "g-water-meter", 5 | "device": { 6 | "name": "Pulsar-M Water Meter", 7 | "id": "pulsar-m-water", 8 | "protocol": "pulsar", 9 | "response_timeout_ms": 500, 10 | "frame_timeout_ms": 300, 11 | "channels": [ 12 | { 13 | "name": "Consumption", 14 | "reg_type": "default", 15 | "address": "0", 16 | "format": "s32", 17 | "type": "water_consumption" 18 | } 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /templates/config-pulsar-water.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "pulsar-water", 3 | "title": "Pulsar Water Meter", 4 | "group": "g-water-meter", 5 | "device": { 6 | "name": "Pulsar Water Meter", 7 | "id": "pulsar-water", 8 | "protocol": "pulsar", 9 | "response_timeout_ms": 500, 10 | "frame_timeout_ms": 300, 11 | "channels": [ 12 | { 13 | "name": "Consumption", 14 | "reg_type": "default", 15 | "address": "0", 16 | "format": "float", 17 | "type": "water_consumption" 18 | } 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /templates/config-tm-p3r3.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "TM-P3R3", 3 | "group": "g-relay", 4 | "device": { 5 | "name": "TM-P3R3", 6 | "id": "tmp3r3", 7 | "frame_timeout_ms": 0, 8 | "channels": [ 9 | { 10 | "name": "Relay 0", 11 | "reg_type": "coil", 12 | "address": 0, 13 | "type": "switch" 14 | }, 15 | { 16 | "name": "Relay 1", 17 | "reg_type": "coil", 18 | "address": 1, 19 | "type": "switch" 20 | }, 21 | { 22 | "name": "Relay 2", 23 | "reg_type": "coil", 24 | "address": 2, 25 | "type": "switch" 26 | }, 27 | { 28 | "name": "Input 0", 29 | "reg_type": "discrete", 30 | "address": 32 31 | }, 32 | { 33 | "name": "Input 1", 34 | "reg_type": "discrete", 35 | "address": 33 36 | }, 37 | { 38 | "name": "Input 2", 39 | "reg_type": "discrete", 40 | "address": 34 41 | } 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/TEMCustomPasswordTest.Combined.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurAccessLevel2SessionSetupResponse() 4 | >> FF 08 02 02 03 04 05 06 07 7B D3 5 | << FF 08 02 C7 F1 6 | EnqueueMilurPhaseCVoltageResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 01 66 03 6F 94 03 03 4E 9 | EnqueueMilurPhaseCCurrentResponse() 10 | >> FF 01 69 80 4E 11 | << FF 01 69 03 F0 D8 FF 53 E0 12 | EnqueueMilurTotalConsumptionResponse() 13 | >> FF 01 76 C1 86 14 | << FF 01 76 04 44 11 10 00 AC 6C 15 | EnqueueMilurFrequencyResponse() 16 | >> FF 01 09 80 66 17 | << FF 01 09 02 A0 C3 B3 D9 18 | SkipNoise() 19 | EnqueueMercury230AccessLevel2SessionSetupResponse() 20 | >> 00 01 02 12 13 14 15 16 17 34 17 21 | << 00 00 01 B0 22 | EnqueueMercury230U1Response() 23 | >> 00 08 11 11 4D BA 24 | << 00 00 40 5E B0 1C 25 | EnqueueMercury230I1Response() 26 | >> 00 08 11 21 4D AE 27 | << 00 00 45 00 32 B4 28 | EnqueueMercury230U2Response() 29 | >> 00 08 11 12 0D BB 30 | << 00 00 EB 5D 8F 2D 31 | EnqueueMercury230PResponse() 32 | >> 00 08 11 00 8D B6 33 | << 00 48 87 70 E2 26 34 | EnqueueMercury230TempResponse() 35 | >> 00 08 11 70 8C 52 36 | << 00 00 18 71 CA 37 | Close() 38 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.Mercury200Energy.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueMercury200EnergyResponse() 3 | >> 00 01 E2 40 27 F4 10 4 | Sleep(100000) 5 | << 00 01 E2 40 27 00 06 21 42 00 02 08 34 00 01 11 11 00 02 22 22 32 42 6 | Close() 7 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.Mercury200Params.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueMercury200ParamResponse() 3 | >> 00 01 E2 40 63 F4 23 4 | Sleep(100000) 5 | << 00 01 E2 40 63 12 34 56 78 76 54 32 8A 8A 6 | Close() 7 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.Mercury230Exception.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230InternalMeterErrorResponse() 7 | >> 00 08 11 12 0D BB 8 | << 00 02 80 71 9 | SkipNoise() 10 | Close() 11 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.Mercury230ReadEnergy.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230EnergyResponse1() 7 | >> 00 05 00 00 10 25 8 | << 00 30 00 28 C5 FF FF FF FF 04 00 9C 95 FF FF FF FF 44 AB 9 | EnqueueMercury230EnergyResponse2() 10 | >> 00 05 00 00 10 25 11 | << 00 30 00 29 C5 FF FF FF FF 04 00 9D 95 FF FF FF FF 45 BB 12 | Close() 13 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.Mercury230ReadParams.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230U1Response() 7 | >> 00 08 11 11 4D BA 8 | << 00 00 40 5E B0 1C 9 | EnqueueMercury230I1Response() 10 | >> 00 08 11 21 4D AE 11 | << 00 00 45 00 32 B4 12 | EnqueueMercury230U2Response() 13 | >> 00 08 11 12 0D BB 14 | << 00 00 EB 5D 8F 2D 15 | EnqueueMercury230PResponse() 16 | >> 00 08 11 00 8D B6 17 | << 00 48 87 70 E2 26 18 | EnqueueMercury230TempResponse() 19 | >> 00 08 11 70 8C 52 20 | << 00 00 18 71 CA 21 | EnqueueMercury230U1Response() 22 | >> 00 08 11 11 4D BA 23 | << 00 00 40 5E B0 1C 24 | EnqueueMercury230I1Response() 25 | >> 00 08 11 21 4D AE 26 | << 00 00 45 00 32 B4 27 | EnqueueMercury230U2Response() 28 | >> 00 08 11 12 0D BB 29 | << 00 00 EB 5D 8F 2D 30 | EnqueueMercury230PResponse() 31 | >> 00 08 11 00 8D B6 32 | << 00 48 87 70 E2 26 33 | EnqueueMercury230TempResponse() 34 | >> 00 08 11 70 8C 52 35 | << 00 00 18 71 CA 36 | Close() 37 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.Mercury230Reconnect.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230NoSessionResponse() 7 | >> 00 08 11 12 0D BB 8 | << 00 05 C1 B3 9 | SkipNoise() 10 | EnqueueMercury230SessionSetupResponse() 11 | >> 00 01 01 01 01 01 01 01 01 77 81 12 | << 00 00 01 B0 13 | EnqueueMercury230U2Response() 14 | >> 00 08 11 12 0D BB 15 | << 00 00 EB 5D 8F 2D 16 | Close() 17 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.MilurException.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurSessionSetupResponse() 4 | >> FF 08 01 FF FF FF FF FF FF 5F ED 5 | << FF 08 01 87 F0 6 | EnqueueMilurExceptionResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 81 07 00 62 28 9 | SkipNoise() 10 | Close() 11 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.MilurQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurSessionSetupResponse() 4 | >> FF 08 01 FF FF FF FF FF FF 5F ED 5 | << FF 08 01 87 F0 6 | EnqueueMilurPhaseCVoltageResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 01 66 03 6F 94 03 03 4E 9 | EnqueueMilurPhaseCCurrentResponse() 10 | >> FF 01 69 80 4E 11 | << FF 01 69 03 F0 D8 FF 53 E0 12 | EnqueueMilurTotalConsumptionResponse() 13 | >> FF 01 76 C1 86 14 | << FF 01 76 04 44 11 10 00 AC 6C 15 | EnqueueMilurFrequencyResponse() 16 | >> FF 01 09 80 66 17 | << FF 01 09 02 A0 C3 B3 D9 18 | EnqueueMilurPhaseCVoltageResponse() 19 | >> FF 01 66 C0 4A 20 | << FF 01 66 03 6F 94 03 03 4E 21 | EnqueueMilurPhaseCCurrentResponse() 22 | >> FF 01 69 80 4E 23 | << FF 01 69 03 F0 D8 FF 53 E0 24 | EnqueueMilurTotalConsumptionResponse() 25 | >> FF 01 76 C1 86 26 | << FF 01 76 04 44 11 10 00 AC 6C 27 | EnqueueMilurFrequencyResponse() 28 | >> FF 01 09 80 66 29 | << FF 01 09 02 A0 C3 B3 D9 30 | Close() 31 | -------------------------------------------------------------------------------- /test/TEMDeviceTest.MilurReconnect.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurSessionSetupResponse() 4 | >> FF 08 01 FF FF FF FF FF FF 5F ED 5 | << FF 08 01 87 F0 6 | EnqueueMilurNoSessionResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 81 08 00 67 D8 9 | SkipNoise() 10 | EnqueueMilurSessionSetupResponse() 11 | >> FF 08 01 FF FF FF FF FF FF 5F ED 12 | << FF 08 01 87 F0 13 | EnqueueMilurPhaseCVoltageResponse() 14 | >> FF 01 66 C0 4A 15 | -------------------------------------------------------------------------------- /test/TIVTMDeviceTest.IVTM7MQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | >> 24 30 30 30 31 52 52 30 30 30 30 30 34 41 44 0D 4 | << 21 30 30 30 31 52 52 43 45 44 33 44 31 34 31 35 46 0D 5 | SkipNoise() 6 | >> 24 30 30 30 31 52 52 30 30 30 34 30 34 42 31 0D 7 | << 21 30 30 30 31 52 52 33 30 39 41 45 42 34 31 34 46 0D 8 | SkipNoise() 9 | >> 24 30 30 30 31 52 52 30 30 30 30 30 34 41 44 0D 10 | << 21 30 30 30 31 52 52 35 45 38 35 43 37 34 31 34 43 0D 11 | Close() 12 | -------------------------------------------------------------------------------- /test/TMercury200Test.BatteryVoltageQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueMercury200BatteryVoltageResponse() 3 | >> FE 12 34 56 29 B7 1C 4 | << FE 12 34 56 29 03 91 B7 65 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TMercury200Test.EnergyQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueMercury200EnergyResponse() 3 | >> FE 12 34 56 27 36 D8 4 | << FE 12 34 56 27 00 06 21 42 00 02 08 34 00 01 11 11 00 02 22 22 2B 25 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TMercury200Test.ParamsQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueMercury200ParamResponse() 3 | >> FE 12 34 56 63 36 EB 4 | << FE 12 34 56 63 12 34 56 78 76 54 32 79 0E 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TMercury230CustomPasswordTest.Test.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230AccessLevel2SessionSetupResponse() 4 | >> 00 01 02 12 13 14 15 16 17 34 17 5 | << 00 00 01 B0 6 | EnqueueMercury230U1Response() 7 | >> 00 08 11 11 4D BA 8 | << 00 00 40 5E B0 1C 9 | EnqueueMercury230I1Response() 10 | >> 00 08 11 21 4D AE 11 | << 00 00 45 00 32 B4 12 | EnqueueMercury230I2Response() 13 | >> 00 08 11 22 0D AF 14 | << 00 00 60 00 28 24 15 | EnqueueMercury230U2Response() 16 | >> 00 08 11 12 0D BB 17 | << 00 00 EB 5D 8F 2D 18 | EnqueueMercury230U3Response() 19 | >> 00 08 11 13 CC 7B 20 | << 00 00 E5 C4 4B 27 21 | EnqueueMercury230PResponse() 22 | >> 00 08 11 00 8D B6 23 | << 00 48 87 70 E2 26 24 | EnqueueMercury230TempResponse() 25 | >> 00 08 11 70 8C 52 26 | << 00 00 18 71 CA 27 | Close() 28 | -------------------------------------------------------------------------------- /test/TMercury230Test.Exception.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230InternalMeterErrorResponse() 7 | >> 00 08 11 12 0D BB 8 | << 00 02 80 71 9 | SkipNoise() 10 | Close() 11 | -------------------------------------------------------------------------------- /test/TMercury230Test.ReadEnergy.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230EnergyResponse1() 7 | >> 00 05 00 00 10 25 8 | << 00 30 00 28 C5 FF FF FF FF 04 00 9C 95 FF FF FF FF 44 AB 9 | EnqueueMercury230EnergyResponse2() 10 | >> 00 05 00 00 10 25 11 | << 00 30 00 29 C5 FF FF FF FF 04 00 9D 95 FF FF FF FF 45 BB 12 | Close() 13 | -------------------------------------------------------------------------------- /test/TMercury230Test.ReadParams.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230U1Response() 7 | >> 00 08 11 11 4D BA 8 | << 00 00 40 5E B0 1C 9 | EnqueueMercury230I1Response() 10 | >> 00 08 11 21 4D AE 11 | << 00 00 45 00 32 B4 12 | EnqueueMercury230I2Response() 13 | >> 00 08 11 22 0D AF 14 | << 00 00 60 00 28 24 15 | EnqueueMercury230U2Response() 16 | >> 00 08 11 12 0D BB 17 | << 00 00 EB 5D 8F 2D 18 | EnqueueMercury230U3Response() 19 | >> 00 08 11 13 CC 7B 20 | << 00 00 E5 C4 4B 27 21 | EnqueueMercury230PResponse() 22 | >> 00 08 11 00 8D B6 23 | << 00 48 87 70 E2 26 24 | EnqueueMercury230TempResponse() 25 | >> 00 08 11 70 8C 52 26 | << 00 00 18 71 CA 27 | EnqueueMercury230U1Response() 28 | >> 00 08 11 11 4D BA 29 | << 00 00 40 5E B0 1C 30 | EnqueueMercury230I1Response() 31 | >> 00 08 11 21 4D AE 32 | << 00 00 45 00 32 B4 33 | EnqueueMercury230I2Response() 34 | >> 00 08 11 22 0D AF 35 | << 00 00 60 00 28 24 36 | EnqueueMercury230U2Response() 37 | >> 00 08 11 12 0D BB 38 | << 00 00 EB 5D 8F 2D 39 | EnqueueMercury230U3Response() 40 | >> 00 08 11 13 CC 7B 41 | << 00 00 E5 C4 4B 27 42 | EnqueueMercury230PResponse() 43 | >> 00 08 11 00 8D B6 44 | << 00 48 87 70 E2 26 45 | EnqueueMercury230TempResponse() 46 | >> 00 08 11 70 8C 52 47 | << 00 00 18 71 CA 48 | Close() 49 | -------------------------------------------------------------------------------- /test/TMercury230Test.Reconnect.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMercury230SessionSetupResponse() 4 | >> 00 01 01 01 01 01 01 01 01 77 81 5 | << 00 00 01 B0 6 | EnqueueMercury230NoSessionResponse() 7 | >> 00 08 11 12 0D BB 8 | << 00 05 C1 B3 9 | SkipNoise() 10 | EnqueueMercury230SessionSetupResponse() 11 | >> 00 01 01 01 01 01 01 01 01 77 81 12 | << 00 00 01 B0 13 | EnqueueMercury230U2Response() 14 | >> 00 08 11 12 0D BB 15 | << 00 00 EB 5D 8F 2D 16 | Close() 17 | -------------------------------------------------------------------------------- /test/TMilur32Test.MilurQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilur32SessionSetupResponse() 4 | >> 0C C3 00 00 08 01 FF FF FF FF FF FF 97 BC 5 | << 0C C3 00 00 08 01 82 C6 6 | EnqueueMilur32TotalConsumptionResponse() 7 | >> 0C C3 00 00 01 76 C4 B0 8 | << 0C C3 00 00 01 76 04 44 11 10 00 6F E4 9 | EnqueueMilur32TotalConsumptionResponse() 10 | >> 0C C3 00 00 01 76 C4 B0 11 | << 0C C3 00 00 01 76 04 44 11 10 00 6F E4 12 | Close() 13 | -------------------------------------------------------------------------------- /test/TMilurCustomPasswordTest.Test.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurAccessLevel2SessionSetupResponse() 4 | >> FF 08 02 02 03 04 05 06 07 7B D3 5 | << FF 08 02 C7 F1 6 | EnqueueMilurPhaseCVoltageResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 01 66 03 6F 94 03 03 4E 9 | EnqueueMilurPhaseCCurrentResponse() 10 | >> FF 01 69 80 4E 11 | << FF 01 69 03 F0 D8 FF 53 E0 12 | EnqueueMilurTotalConsumptionResponse() 13 | >> FF 01 76 C1 86 14 | << FF 01 76 04 44 11 10 00 AC 6C 15 | EnqueueMilurFrequencyResponse() 16 | >> FF 01 09 80 66 17 | << FF 01 09 02 A0 C3 B3 D9 18 | Close() 19 | -------------------------------------------------------------------------------- /test/TMilurTest.Exception.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurSessionSetupResponse() 4 | >> FF 08 01 FF FF FF FF FF FF 5F ED 5 | << FF 08 01 87 F0 6 | EnqueueMilurExceptionResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 81 07 00 62 28 9 | SkipNoise() 10 | Close() 11 | -------------------------------------------------------------------------------- /test/TMilurTest.Query.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurSessionSetupResponse() 4 | >> FF 08 01 FF FF FF FF FF FF 5F ED 5 | << FF 08 01 87 F0 6 | EnqueueMilurPhaseCVoltageResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 01 66 03 6F 94 03 03 4E 9 | EnqueueMilurPhaseCCurrentResponse() 10 | >> FF 01 69 80 4E 11 | << FF 01 69 03 F0 D8 FF 53 E0 12 | EnqueueMilurTotalConsumptionResponse() 13 | >> FF 01 76 C1 86 14 | << FF 01 76 04 44 11 10 00 AC 6C 15 | EnqueueMilurFrequencyResponse() 16 | >> FF 01 09 80 66 17 | << FF 01 09 02 A0 C3 B3 D9 18 | EnqueueMilurPhaseCVoltageResponse() 19 | >> FF 01 66 C0 4A 20 | << FF 01 66 03 6F 94 03 03 4E 21 | EnqueueMilurPhaseCCurrentResponse() 22 | >> FF 01 69 80 4E 23 | << FF 01 69 03 F0 D8 FF 53 E0 24 | EnqueueMilurTotalConsumptionResponse() 25 | >> FF 01 76 C1 86 26 | << FF 01 76 04 44 11 10 00 AC 6C 27 | EnqueueMilurFrequencyResponse() 28 | >> FF 01 09 80 66 29 | << FF 01 09 02 A0 C3 B3 D9 30 | Close() 31 | -------------------------------------------------------------------------------- /test/TMilurTest.Reconnect.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueMilurSessionSetupResponse() 4 | >> FF 08 01 FF FF FF FF FF FF 5F ED 5 | << FF 08 01 87 F0 6 | EnqueueMilurNoSessionResponse() 7 | >> FF 01 66 C0 4A 8 | << FF 81 08 00 67 D8 9 | SkipNoise() 10 | EnqueueMilurSessionSetupResponse() 11 | >> FF 08 01 FF FF FF FF FF FF 5F ED 12 | << FF 08 01 87 F0 13 | EnqueueMilurPhaseCVoltageResponse() 14 | >> FF 01 66 C0 4A 15 | << FF 01 66 03 6F 94 03 03 4E 16 | -------------------------------------------------------------------------------- /test/TModbusTest.CRCError.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueInvalidCRCCoilReadResponse() 3 | >> 01 01 00 00 00 01 FD CA 4 | << 01 01 01 02 D0 4A 5 | SkipNoise() 6 | Close() 7 | -------------------------------------------------------------------------------- /test/TModbusTest.Errors.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueCoilReadResponse() 3 | >> 01 01 00 00 00 02 BD CB 4 | << 01 81 01 81 90 5 | EnqueueDiscreteReadResponse() 6 | >> 01 02 00 14 00 01 F9 CE 7 | << 01 82 02 C1 61 8 | EnqueueHoldingReadU16Response() 9 | >> 01 03 00 46 00 01 65 DF 10 | << 01 03 02 00 15 79 8B 11 | EnqueueInputReadU16Response() 12 | >> 01 04 00 28 00 01 B1 C2 13 | << 01 04 02 00 66 39 1A 14 | EnqueueHoldingReadS64Response() 15 | >> 01 03 00 1E 00 04 24 0F 16 | << 01 03 08 01 02 03 04 05 06 07 08 65 13 17 | Close() 18 | -------------------------------------------------------------------------------- /test/TModbusTest.HoldingSingleMulti.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueHoldingSingleWriteU16Response() 3 | >> 01 06 00 5E 0F 41 2D D8 4 | << 01 06 00 5E 0F 41 2D D8 5 | EnqueueHoldingSingleWriteU64Response() 6 | >> 01 06 00 5D 06 07 5A 7A 7 | << 01 06 00 5D 06 07 5A 7A 8 | EnqueueHoldingSingleWriteU64Response() 9 | >> 01 06 00 5C 04 05 8B 1B 10 | << 01 06 00 5C 04 05 8B 1B 11 | EnqueueHoldingSingleWriteU64Response() 12 | >> 01 06 00 5B 02 03 B9 78 13 | << 01 06 00 5B 02 03 B9 78 14 | EnqueueHoldingSingleWriteU64Response() 15 | >> 01 06 00 5A 00 01 68 19 16 | << 01 06 00 5A 00 01 68 19 17 | EnqueueHoldingMultiWriteU16Response() 18 | >> 01 10 00 63 00 01 02 01 23 EF 8A 19 | << 01 10 00 63 00 01 F1 D7 20 | EnqueueHoldingMultiWriteU64Response() 21 | >> 01 10 00 5F 00 04 08 01 23 45 67 89 AB CD EF C4 5D 22 | << 01 10 00 5F 00 04 F1 D8 23 | Close() 24 | -------------------------------------------------------------------------------- /test/TModbusTest.MinReadRegisters.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueHoldingReadU16Min2ReadResponse() 3 | >> 01 03 00 6E 00 02 A5 D6 4 | << 01 03 02 00 15 79 8B 5 | -------------------------------------------------------------------------------- /test/TModbusTest.Query.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueCoilReadResponse() 3 | >> 01 01 00 00 00 02 BD CB 4 | << 01 01 01 02 D0 49 5 | EnqueueDiscreteReadResponse() 6 | >> 01 02 00 14 00 01 F9 CE 7 | << 01 02 01 01 60 48 8 | EnqueueHoldingReadU16Response() 9 | >> 01 03 00 46 00 01 65 DF 10 | << 01 03 02 00 15 79 8B 11 | EnqueueInputReadU16Response() 12 | >> 01 04 00 28 00 01 B1 C2 13 | << 01 04 02 00 66 39 1A 14 | EnqueueHoldingReadS64Response() 15 | >> 01 03 00 1E 00 04 24 0F 16 | << 01 03 08 01 02 03 04 05 06 07 08 65 13 17 | Close() 18 | -------------------------------------------------------------------------------- /test/TModbusTest.ReadHoldingRegiterWithOffsetWriteOptions.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueHoldingReadU16ResponseWithOffsetWriteOptions() 3 | >> 01 03 00 6F 00 01 B4 17 4 | << 01 03 02 00 15 79 8B 5 | -------------------------------------------------------------------------------- /test/TModbusTest.ReadHoldingRegiterWithWriteAddress.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueHoldingReadU16ResponseWithWriteAddress() 3 | >> 01 03 00 6E 00 01 E5 D7 4 | << 01 03 02 00 15 79 8B 5 | -------------------------------------------------------------------------------- /test/TModbusTest.ReadString.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueStringReadResponse() 3 | >> 01 03 00 78 00 10 C4 1F 4 | << 01 03 20 00 32 00 2E 00 34 00 2E 00 32 00 2D 00 72 00 63 00 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0C 84 5 | EnqueueStringReadResponse() 6 | >> 01 03 00 78 00 10 C4 1F 7 | << 01 03 20 00 32 00 2E 00 34 00 2E 00 32 00 2D 00 72 00 63 00 31 00 00 00 31 00 31 00 31 00 31 00 31 00 31 63 F5 8 | EnqueueStringReadResponse() 9 | >> 01 03 00 78 00 10 C4 1F 10 | << 01 03 20 00 32 00 2E 00 34 00 2E 00 32 00 2D 00 72 00 63 00 31 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F2 04 11 | EnqueueStringReadResponse() 12 | >> 01 03 00 78 00 10 C4 1F 13 | << 01 03 20 00 32 00 2E 00 34 00 2E 00 32 00 2D 00 72 00 63 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 C1 A8 14 | Close() 15 | -------------------------------------------------------------------------------- /test/TModbusTest.ReadString8.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueString8ReadResponse() 3 | >> 01 03 00 8E 00 08 24 27 4 | << 01 03 10 32 2E 34 2E 32 2D 72 63 31 00 00 00 00 00 00 00 77 0A 5 | EnqueueString8ReadResponse() 6 | >> 01 03 00 8E 00 08 24 27 7 | << 01 03 10 32 2E 34 2E 32 2D 72 63 31 00 AA BB CC DD EE FF 29 91 8 | EnqueueString8ReadResponse() 9 | >> 01 03 00 8E 00 08 24 27 10 | << 01 03 10 32 2E 34 2E 32 2D 72 63 31 FF FF FF FF FF FF FF 79 8A 11 | EnqueueString8ReadResponse() 12 | >> 01 03 00 8E 00 08 24 27 13 | << 01 03 10 32 2E 34 2E 32 2D 72 63 31 32 33 34 35 36 37 38 28 EE 14 | Close() 15 | -------------------------------------------------------------------------------- /test/TModbusTest.SkipNoiseAtPacketEnd.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueReadResponseWithNoiseAtTheEnd() 3 | >> 01 03 27 2E 00 01 EE B7 4 | << 01 03 02 11 78 B4 36 5 | << B0 AA 6 | EnqueueReadResponseWithNoiseAtTheEnd() 7 | >> 01 03 27 2E 00 01 EE B7 8 | << 01 03 02 11 78 B4 36 9 | -------------------------------------------------------------------------------- /test/TModbusTest.WriteHoldingRegiterWithOffsetWriteOptions.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueHoldingWriteU16ResponseWithOffsetWriteOptions() 3 | >> 01 06 00 74 00 14 C9 DF 4 | << 01 06 00 74 00 14 C9 DF 5 | -------------------------------------------------------------------------------- /test/TModbusTest.WriteHoldingRegiterWithWriteAddress.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueHoldingWriteU16ResponseWithWriteAddress() 3 | >> 01 06 00 73 11 9C 74 28 4 | << 01 06 00 73 11 9C 74 28 5 | -------------------------------------------------------------------------------- /test/TModbusTest.WriteOnlyHoldingRegiter.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | -------------------------------------------------------------------------------- /test/TModbusTest.WriteOnlyHoldingRegiterNeg.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | -------------------------------------------------------------------------------- /test/TModbusTest.WriteOnlyRegisters.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueCoilWriteResponse() 3 | >> 01 05 00 00 FF 00 8C 3A 4 | << 01 05 00 00 FF 00 8C 3A 5 | EnqueueHoldingWriteU16Response() 6 | >> 01 06 00 46 0F 41 AD DF 7 | << 01 06 00 46 0F 41 AD DF 8 | Close() 9 | -------------------------------------------------------------------------------- /test/TModbusTest.WriteString.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueStringWriteResponse() 3 | >> 01 10 00 78 00 09 12 00 4C 00 61 00 74 00 65 00 72 00 61 00 6C 00 75 00 73 B7 3D 4 | << 01 10 00 78 00 09 80 16 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TModbusTest.WriteString8.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueString8WriteResponse() 3 | >> 01 10 00 8E 00 05 0A 4C 61 74 65 72 61 6C 75 73 00 45 7E 4 | << 01 10 00 8E 00 05 60 21 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TModbusTest.WrongFunctionCode.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueWrongFunctionCodeCoilReadResponse() 3 | >> 01 01 00 00 00 01 FD CA 4 | << 01 02 01 01 60 48 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TModbusTest.WrongFunctionCodeWithException.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueWrongFunctionCodeCoilReadResponse() 3 | >> 01 01 00 00 00 01 FD CA 4 | << 01 82 02 C1 61 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TModbusTest.WrongFunctionCodeWithExceptionWrite.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueWrongFunctionCodeCoilWriteResponse() 3 | >> 01 05 00 00 FF 00 8C 3A 4 | << 01 87 02 C2 31 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TModbusTest.WrongFunctionCodeWrite.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueWrongFunctionCodeCoilWriteResponse() 3 | >> 01 05 00 00 FF 00 8C 3A 4 | << 01 07 00 00 FF 00 F5 FA 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TModbusTest.WrongResponseDataSize.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueWrongDataSizeReadResponse() 3 | >> 01 01 00 00 00 01 FD CA 4 | << 01 01 02 02 D0 B9 5 | SkipNoise() 6 | Close() 7 | -------------------------------------------------------------------------------- /test/TModbusTest.WrongSlaveId.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueWrongSlaveIdCoilReadResponse() 3 | >> 01 01 00 00 00 01 FD CA 4 | << 02 01 01 01 90 0C 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TModbusTest.WrongSlaveIdWrite.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueWrongSlaveIdCoilWriteResponse() 3 | >> 01 05 00 00 FF 00 8C 3A 4 | << 02 05 00 00 FF 00 8C 09 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TNevaTest.PrepareOk.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueStartSession() 4 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 5 | << 2F 54 50 43 35 4E 45 56 41 4D 54 33 32 34 2E 32 33 30 37 0D 0A 6 | EnqueueGoToProgMode() 7 | >> 06 30 35 31 0D 0A 8 | << 01 50 30 02 28 30 30 30 30 30 30 30 30 29 03 60 9 | EnqueueSendPassword() 10 | >> 01 50 31 02 28 30 30 30 30 30 30 30 30 29 03 61 11 | << 06 12 | Close() 13 | -------------------------------------------------------------------------------- /test/TNevaTest.SendPasswordError.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueStartSession() 4 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 5 | << 2F 54 50 43 35 4E 45 56 41 4D 54 33 32 34 2E 32 33 30 37 0D 0A 6 | EnqueueGoToProgMode() 7 | >> 06 30 35 31 0D 0A 8 | << 01 50 30 02 28 30 30 30 30 30 30 30 30 29 03 60 9 | EnqueueSendPassword() 10 | >> 01 50 31 02 28 30 30 30 30 30 30 30 30 29 03 61 11 | << 07 12 | EnqueueEndSession() 13 | >> 01 42 30 03 71 14 | Close() 15 | -------------------------------------------------------------------------------- /test/TNevaTest.StartSessionError.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueStartSession() 4 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 5 | EnqueueEndSession() 6 | >> 01 42 30 03 71 7 | SkipNoise() 8 | EnqueueStartSession() 9 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 10 | EnqueueEndSession() 11 | >> 01 42 30 03 71 12 | SkipNoise() 13 | EnqueueStartSession() 14 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 15 | EnqueueEndSession() 16 | >> 01 42 30 03 71 17 | SkipNoise() 18 | EnqueueStartSession() 19 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 20 | EnqueueEndSession() 21 | >> 01 42 30 03 71 22 | SkipNoise() 23 | EnqueueStartSession() 24 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 25 | EnqueueEndSession() 26 | >> 01 42 30 03 71 27 | Close() 28 | -------------------------------------------------------------------------------- /test/TNevaTest.SwitchToProgModeError.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | EnqueueStartSession() 4 | >> 2F 3F 30 30 30 30 30 32 30 31 21 0D 0A 5 | << 2F 54 50 43 35 4E 45 56 41 4D 54 33 32 34 2E 32 33 30 37 0D 0A 6 | EnqueueGoToProgMode() 7 | >> 06 30 35 31 0D 0A 8 | << 01 50 30 02 28 30 30 30 30 30 30 30 30 29 03 61 9 | EnqueueEndSession() 10 | >> 01 42 30 03 71 11 | Close() 12 | -------------------------------------------------------------------------------- /test/TPtyBasedFakeSerialTest.Expect.dat: -------------------------------------------------------------------------------- 1 | foo() 2 | >> 01 02 03 3 | << 10 20 30 4 | bar() 5 | >> 11 12 13 6 | << 21 22 23 7 | (pty-based fake serial terminating) 8 | -------------------------------------------------------------------------------- /test/TPtyBasedFakeSerialTest.Forward.dat: -------------------------------------------------------------------------------- 1 | >> 01 02 03 2 | << 10 20 30 3 | >> 11 12 13 4 | << 21 22 23 5 | >> 01 02 03 6 | << 10 20 30 7 | >> 11 12 13 8 | << 21 22 23 9 | >> 01 02 03 10 | << 10 20 30 11 | >> 11 12 13 12 | << 21 22 23 13 | (pty-based fake serial -- stopping forwarding) 14 | -------------------------------------------------------------------------------- /test/TPulsarDeviceTest.PulsarHeatMeterFloatQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | SkipNoise() 3 | >> 00 10 70 80 01 0E 04 00 00 00 00 00 7C A7 4 | << 00 10 70 80 01 0E 5A B3 C5 41 00 00 18 DB 5 | Close() 6 | -------------------------------------------------------------------------------- /test/TS2KDeviceTest.TestSetRelayState.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueSetRelayOnResponse() 3 | >> 01 06 00 15 01 01 4E 4 | << 01 05 16 01 01 4D 5 | EnqueueSetRelayOffResponse() 6 | >> 01 06 00 15 01 02 AC 7 | << 01 05 16 01 02 AF 8 | -------------------------------------------------------------------------------- /test/TSerialClientIntegrationTest.SlaveIdCollision.dat: -------------------------------------------------------------------------------- 1 | Subscribe: /devices/+/meta/driver (QoS 0) 2 | stop: serial-client-integration-test 3 | -------------------------------------------------------------------------------- /test/TSerialClientReopenTest.ReopenTimeout.dat: -------------------------------------------------------------------------------- 1 | >>> Cycle() [port open error] 2 | Error Callback: : read error 3 | fake_serial_device '1': transfer FAIL 4 | fake_serial_device '1': disconnected 5 | Error Callback: : read error 6 | fake_serial_device '1': transfer FAIL 7 | >>> Cycle() [port open error2] 8 | fake_serial_device '1': transfer FAIL 9 | fake_serial_device '1': transfer FAIL 10 | >>> Cycle() [successful port open] 11 | Open() 12 | Sleep(100000) 13 | fake_serial_device '1': read address '0' value '0' 14 | fake_serial_device '1': transfer OK 15 | fake_serial_device '1': reconnected 16 | fake_serial_device '1': read address '1' value '0' 17 | Read Callback: becomes 0 18 | Error Callback: : no error 19 | Read Callback: becomes 0 20 | Error Callback: : no error 21 | -------------------------------------------------------------------------------- /test/TSerialClientTest.BCD16.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 0x1234 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value '4660' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | Read Callback: becomes 1234 9 | Error Callback: : no error 10 | >>> client -> server: 1234 11 | >>> Cycle() 12 | fake_serial_device '1': write to address '20' value '4660' 13 | Read Callback: becomes 1234 [unchanged] 14 | fake_serial_device '1': read address '20' value '4660' 15 | Read Callback: becomes 1234 [unchanged] 16 | -------------------------------------------------------------------------------- /test/TSerialClientTest.BCD24.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 0x0034 0x5678 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value '3430008' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | Read Callback: becomes 345678 9 | Error Callback: : no error 10 | >>> client -> server: 567890 11 | >>> Cycle() 12 | fake_serial_device '1': write to address '20' value '5666960' 13 | Read Callback: becomes 567890 14 | fake_serial_device '1': read address '20' value '5666960' 15 | Read Callback: becomes 567890 [unchanged] 16 | -------------------------------------------------------------------------------- /test/TSerialClientTest.BCD32.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 0x1234 0x5678 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value '305419896' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | Read Callback: becomes 12345678 9 | Error Callback: : no error 10 | >>> client -> server: 12345678 11 | >>> Cycle() 12 | fake_serial_device '1': write to address '20' value '305419896' 13 | Read Callback: becomes 12345678 [unchanged] 14 | fake_serial_device '1': read address '20' value '305419896' 15 | Read Callback: becomes 12345678 [unchanged] 16 | >>> client -> server: 567890 17 | >>> Cycle() 18 | fake_serial_device '1': write to address '20' value '5666960' 19 | Read Callback: becomes 567890 20 | fake_serial_device '1': read address '20' value '5666960' 21 | Read Callback: becomes 567890 [unchanged] 22 | -------------------------------------------------------------------------------- /test/TSerialClientTest.BCD8.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 0x12 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value '18' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | Read Callback: becomes 12 9 | Error Callback: : no error 10 | >>> client -> server: 12 11 | >>> Cycle() 12 | fake_serial_device '1': write to address '20' value '18' 13 | Read Callback: becomes 12 [unchanged] 14 | fake_serial_device '1': read address '20' value '18' 15 | Read Callback: becomes 12 [unchanged] 16 | -------------------------------------------------------------------------------- /test/TSerialClientTest.Char8.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 65, 66 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value '65' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | fake_serial_device '1': read address '30' value '66' 9 | Read Callback: becomes A 10 | Error Callback: : no error 11 | Read Callback: becomes B 12 | Error Callback: : no error 13 | >>> client -> server: '!' 14 | >>> Cycle() 15 | fake_serial_device '1': write to address '20' value '33' 16 | Read Callback: becomes ! 17 | fake_serial_device '1': read address '20' value '33' 18 | fake_serial_device '1': read address '30' value '66' 19 | Read Callback: becomes ! [unchanged] 20 | Read Callback: becomes B [unchanged] 21 | -------------------------------------------------------------------------------- /test/TSerialClientTest.PortOpenError.dat: -------------------------------------------------------------------------------- 1 | >>> Cycle() [port open error] 2 | Error Callback: : read error 3 | fake_serial_device '1': transfer FAIL 4 | fake_serial_device '1': disconnected 5 | Error Callback: : read error 6 | fake_serial_device '1': transfer FAIL 7 | >>> Cycle() [port open error2] 8 | fake_serial_device '1': transfer FAIL 9 | fake_serial_device '1': transfer FAIL 10 | >>> Cycle() [successful port open] 11 | Open() 12 | Sleep(100000) 13 | fake_serial_device '1': read address '0' value '0' 14 | fake_serial_device '1': transfer OK 15 | fake_serial_device '1': reconnected 16 | fake_serial_device '1': read address '1' value '0' 17 | Read Callback: becomes 0 18 | Error Callback: : no error 19 | Read Callback: becomes 0 20 | Error Callback: : no error 21 | -------------------------------------------------------------------------------- /test/TSerialClientTest.S64.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 10, 20 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value '47851549213065437' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | fake_serial_device '1': read address '30' value '18446744073709551615' 9 | Read Callback: becomes 47851549213065437 10 | Error Callback: : no error 11 | Read Callback: becomes -1 12 | Error Callback: : no error 13 | >>> client -> server: 10 14 | >>> Cycle() 15 | fake_serial_device '1': write to address '20' value '10' 16 | Read Callback: becomes 10 17 | fake_serial_device '1': read address '20' value '10' 18 | fake_serial_device '1': read address '30' value '18446744073709551615' 19 | Read Callback: becomes 10 [unchanged] 20 | Read Callback: becomes -1 [unchanged] 21 | >>> client -> server: -2 22 | >>> Cycle() 23 | fake_serial_device '1': write to address '20' value '18446744073709551614' 24 | Read Callback: becomes -2 25 | fake_serial_device '1': read address '20' value '18446744073709551614' 26 | fake_serial_device '1': read address '30' value '18446744073709551615' 27 | Read Callback: becomes -2 [unchanged] 28 | Read Callback: becomes -1 [unchanged] 29 | -------------------------------------------------------------------------------- /test/TSerialClientTest.String.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 40ba401f7ced9168 , 4093b148b4395810 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value 'Hello, world!' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | fake_serial_device '1': read address '62' value 'abcd' 9 | Read Callback: becomes Hello, world! 10 | Error Callback: : no error 11 | Read Callback: becomes abcd 12 | Error Callback: : no error 13 | >>> client -> server: 10 14 | >>> Cycle() 15 | fake_serial_device '1': write to address '20' value 'computer' 16 | Read Callback: becomes computer 17 | fake_serial_device '1': read address '20' value 'computer' 18 | fake_serial_device '1': read address '62' value 'abcd' 19 | Read Callback: becomes computer [unchanged] 20 | Read Callback: becomes abcd [unchanged] 21 | -------------------------------------------------------------------------------- /test/TSerialClientTest.WordSwap.dat: -------------------------------------------------------------------------------- 1 | >>> server -> client: 0x00BB, 0x00AA 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': read address '20' value '12255402' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | fake_serial_device '1': read address '24' value '0' 9 | Read Callback: becomes 11141307 10 | Error Callback: : no error 11 | Read Callback: becomes 0 12 | Error Callback: : no error 13 | >>> client -> server: -2 14 | >>> Cycle() 15 | fake_serial_device '1': write to address '20' value '4294901759' 16 | Read Callback: becomes -2 17 | fake_serial_device '1': read address '20' value '4294901759' 18 | fake_serial_device '1': read address '24' value '0' 19 | Read Callback: becomes -2 [unchanged] 20 | Read Callback: becomes 0 [unchanged] 21 | >>> client -> server: 10 22 | >>> Cycle() 23 | fake_serial_device '1': write to address '24' value '62206846038638762' 24 | Read Callback: becomes 47851549213065437 25 | fake_serial_device '1': read address '20' value '4294901759' 26 | fake_serial_device '1': read address '24' value '62206846038638762' 27 | Read Callback: becomes -2 [unchanged] 28 | Read Callback: becomes 47851549213065437 [unchanged] 29 | -------------------------------------------------------------------------------- /test/TSerialClientTest.Write.dat: -------------------------------------------------------------------------------- 1 | >>> Cycle() 2 | Open() 3 | Sleep(100000) 4 | fake_serial_device '1': read address '1' value '0' 5 | fake_serial_device '1': transfer OK 6 | fake_serial_device '1': reconnected 7 | fake_serial_device '1': read address '20' value '0' 8 | Read Callback: becomes 0 9 | Error Callback: : no error 10 | Read Callback: becomes 0 11 | Error Callback: : no error 12 | >>> Cycle() 13 | fake_serial_device '1': write to address '1' value '1' 14 | Read Callback: becomes 1 15 | fake_serial_device '1': write to address '20' value '4242' 16 | Read Callback: becomes 4242 17 | fake_serial_device '1': read address '1' value '1' 18 | fake_serial_device '1': read address '20' value '4242' 19 | Read Callback: becomes 1 [unchanged] 20 | Read Callback: becomes 4242 [unchanged] 21 | >>> Cycle() 22 | fake_serial_device '1': read address '1' value '1' 23 | fake_serial_device '1': read address '20' value '4242' 24 | Read Callback: becomes 1 [unchanged] 25 | Read Callback: becomes 4242 [unchanged] 26 | >>> Cycle() 27 | fake_serial_device '1': read address '1' value '1' 28 | fake_serial_device '1': read address '20' value '4242' 29 | Read Callback: becomes 1 [unchanged] 30 | Read Callback: becomes 4242 [unchanged] 31 | -------------------------------------------------------------------------------- /test/TSerialClientTest.offset.dat: -------------------------------------------------------------------------------- 1 | >>> client -> server: -87 (scaled) 2 | >>> Cycle() 3 | Open() 4 | Sleep(100000) 5 | fake_serial_device '1': write to address '24' value '65512' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | Read Callback: becomes -87 9 | Error Callback: : no error 10 | fake_serial_device '1': read address '24' value '65512' 11 | Read Callback: becomes -87 [unchanged] 12 | -------------------------------------------------------------------------------- /test/TSerialClientTestWithSetupRegisters.SetupFail.dat: -------------------------------------------------------------------------------- 1 | fake_serial_device: block address '101' for writing 2 | Open() 3 | Sleep(100000) 4 | fake_serial_device '1': write to address '100' value '10' 5 | fake_serial_device '1': write address '101' failed: 'Serial protocol error: write blocked' 6 | fake_serial_device '1': transfer FAIL 7 | fake_serial_device '1': disconnected 8 | Error Callback: : read error 9 | fake_serial_device: unblock address '101' for writing 10 | Sleep(100000) 11 | fake_serial_device '1': write to address '100' value '10' 12 | fake_serial_device '1': write to address '101' value '11' 13 | fake_serial_device '1': write to address '102' value '12' 14 | fake_serial_device '1': transfer OK 15 | fake_serial_device '1': reconnected 16 | fake_serial_device '1': read address '20' value '0' 17 | Read Callback: becomes 0 18 | Error Callback: : no error 19 | -------------------------------------------------------------------------------- /test/TSerialClientTestWithSetupRegisters.SetupOk.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | Sleep(100000) 3 | fake_serial_device '1': write to address '100' value '10' 4 | fake_serial_device '1': write to address '101' value '11' 5 | fake_serial_device '1': write to address '102' value '12' 6 | fake_serial_device '1': transfer OK 7 | fake_serial_device '1': reconnected 8 | fake_serial_device '1': read address '20' value '0' 9 | Read Callback: becomes 0 10 | Error Callback: : no error 11 | -------------------------------------------------------------------------------- /test/TSerialPortTest.TestImxBug.dat: -------------------------------------------------------------------------------- 1 | SkipNoise() 2 | SkipNoise() 3 | Reopen() 4 | ReadByte() 5 | SkipNoise() 6 | Reopen() 7 | Reopen() 8 | Reopen() 9 | (pty-based fake serial -- stopping forwarding) 10 | -------------------------------------------------------------------------------- /test/TSerialPortTest.TestSkipNoise.dat: -------------------------------------------------------------------------------- 1 | SkipNoise() 2 | SkipNoise() 3 | ReadByte() 4 | >> 01 02 03 04 5 | (pty-based fake serial -- stopping forwarding) 6 | -------------------------------------------------------------------------------- /test/TUnielDeviceTest.TestQuery.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueVoltageQueryResponse() 3 | >> FF FF 05 01 00 0A 00 10 4 | << FF FF 05 00 9A 0A 00 A9 5 | EnqueueVoltageQueryResponse() 6 | >> FF FF 05 01 00 0A 00 10 7 | << FF FF 05 00 9A 0A 00 A9 8 | EnqueueRelayOffQueryResponse() 9 | >> FF FF 05 01 00 1B 00 21 10 | << FF FF 05 00 00 1B 00 20 11 | EnqueueRelayOnQueryResponse() 12 | >> FF FF 05 01 00 1B 00 21 13 | << FF FF 05 00 FF 1B 00 1F 14 | EnqueueThreshold0QueryResponse() 15 | >> FF FF 05 01 00 02 00 08 16 | << FF FF 05 00 70 02 00 77 17 | EnqueueBrightnessQueryResponse() 18 | >> FF FF 05 01 00 41 00 47 19 | << FF FF 05 00 42 41 00 88 20 | -------------------------------------------------------------------------------- /test/TUnielDeviceTest.TestSetBrightness.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueSetBrightnessResponse() 3 | >> FF FF 0A 01 42 01 00 4E 4 | << FF FF 0A 00 42 01 00 4D 5 | -------------------------------------------------------------------------------- /test/TUnielDeviceTest.TestSetParam.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueSetLowThreshold0Response() 3 | >> FF FF 06 01 70 02 00 79 4 | << FF FF 06 00 70 02 00 78 5 | -------------------------------------------------------------------------------- /test/TUnielDeviceTest.TestSetRelayState.dat: -------------------------------------------------------------------------------- 1 | Open() 2 | EnqueueSetRelayOnResponse() 3 | >> FF FF 06 01 FF 1B 00 21 4 | << FF FF 06 00 FF 1B 00 20 5 | EnqueueSetRelayOffResponse() 6 | >> FF FF 06 01 00 1B 00 22 7 | << FF FF 06 00 00 1B 00 21 8 | -------------------------------------------------------------------------------- /test/a_ok_test.cpp: -------------------------------------------------------------------------------- 1 | #include "devices/curtains/a_ok_device.h" 2 | #include "test_utils.h" 3 | #include 4 | 5 | using namespace Aok; 6 | using namespace WBMQTT::Testing; 7 | 8 | TEST(TAokTest, MakeRequest) 9 | { 10 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x10, 0x2, 0x3, 0x0a, 0xdd), {0x9a, 0x10, 0x2, 0x3, 0x0a, 0xdd, 0xc6})); 11 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0xcc), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0xcc, 0xc6})); 12 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0xee), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0xee, 0xe4})); 13 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0x0d), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0x0d, 0x07})); 14 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0x0e), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0x0e, 0x04})); 15 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0x01), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0x01, 0x0b})); 16 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0x02), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0x02, 0x08})); 17 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0x03), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0x03, 0x09})); 18 | ASSERT_TRUE(ArraysMatch(MakeRequest(0x0, 0x0, 0x0, 0x0a, 0x04), {0x9a, 0x0, 0x0, 0x0, 0x0a, 0x04, 0x0e})); 19 | } 20 | -------------------------------------------------------------------------------- /test/abt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -u -e 3 | data_dir="$(dirname "$0")" 4 | 5 | usage() { 6 | echo "usage: $0 show|accept" 1>&2 7 | exit 1 8 | } 9 | 10 | show() { 11 | diff -uN "$1" "$2" || 12 | if [ $? = 2 ]; then 13 | echo "DIFF FAILED" 1>&2 14 | exit 1 15 | fi 16 | } 17 | 18 | accept() { 19 | echo "ACCEPT: $1" 1>& 2 20 | mv "$2" "$1" 21 | } 22 | 23 | process_files() { 24 | found= 25 | for out_filename in "$data_dir"/*.dat.out; do 26 | if [ -e "$out_filename" ]; then 27 | found=y 28 | filename="$(echo "$out_filename" | sed 's/\.out//g')" 29 | "$1" "$filename" "$out_filename" 30 | fi 31 | done 32 | if [ -z "$found" ]; then 33 | echo "no diffs found" 1>& 2 34 | fi 35 | } 36 | 37 | if [ $# -lt 1 ]; then 38 | usage 39 | fi 40 | 41 | case "$1" in 42 | show) 43 | process_files show 44 | ;; 45 | accept) 46 | process_files accept 47 | ;; 48 | *) 49 | usage 50 | esac 51 | -------------------------------------------------------------------------------- /test/channel_value_test.cpp: -------------------------------------------------------------------------------- 1 | #include "register_value.h" 2 | #include "gtest/gtest.h" 3 | #include 4 | 5 | TEST(RegisterValueTest, Get) 6 | { 7 | uint64_t val = 0x1122334455667788; 8 | TRegisterValue registerValue{val}; 9 | EXPECT_EQ(val, registerValue.Get()); 10 | EXPECT_EQ(val & 0xffffffff, registerValue.Get()); 11 | EXPECT_EQ(val & 0xffff, registerValue.Get()); 12 | EXPECT_EQ(val & 0xff, registerValue.Get()); 13 | } 14 | 15 | TEST(RegisterValueTest, Set) 16 | { 17 | TRegisterValue registerValue; 18 | uint64_t val = 0x1122334455667788; 19 | registerValue.Set(val); 20 | EXPECT_EQ(val, registerValue.Get()); 21 | } 22 | 23 | TEST(RegisterValueTest, String) 24 | { 25 | TRegisterValue value; 26 | std::string str = "abcdefgh1423"; 27 | value.Set(str); 28 | EXPECT_EQ(str, value.Get()); 29 | } -------------------------------------------------------------------------------- /test/configs/config-dlms-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "port_type" : "serial", 6 | "path" : "/dev/ttyNSC1", 7 | "devices" : [ 8 | { 9 | "name": "DLMS", 10 | "id": "dlms", 11 | "slave_id": 20, 12 | "dlms_auth": 1, 13 | "dlms_client_address": 32, 14 | "password": ["0x31", "0x31", "0x31", "0x31", "0x31", "0x31"], 15 | "response_timeout_ms": 1000, 16 | "frame_timeout_ms" : 20, 17 | "protocol": "dlms", 18 | "channels": [ 19 | { 20 | "address" : "0.0.96.9.0.255", 21 | "name" : "Temperature", 22 | "reg_type" : "default", 23 | "type" : "temperature" 24 | } 25 | ] 26 | } 27 | ] 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /test/configs/config-lls-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "max_unchanged_interval": 100, 4 | "ports": [ 5 | { 6 | "path" : "/dev/ttyNSC0", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 1, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "slave_id": "1", 15 | "device_type": "ESCORT DB-2" 16 | } 17 | ] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /test/configs/config-mercury200-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "max_unchanged_interval": 100, 4 | "ports": [ 5 | { 6 | "port_type" : "serial", 7 | "path" : "/dev/ttyNSC0", 8 | "baud_rate": 9600, 9 | "parity": "N", 10 | "data_bits": 8, 11 | "stop_bits": 1, 12 | "enabled": true, 13 | "devices" : [ 14 | { 15 | "slave_id": "0xFE123456", 16 | "device_type": "Mercury 200.02" 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/configs/config-mercury230-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "max_unchanged_interval": 100, 4 | "ports": [ 5 | { 6 | "path" : "/dev/ttyNSC0", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 1, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "slave_id": "0", 15 | "device_type": "mercury230" 16 | } 17 | ] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /test/configs/config-milur-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "max_unchanged_interval": 100, 4 | "ports": [ 5 | { 6 | "port_type" : "serial", 7 | "path" : "/dev/ttyNSC0", 8 | "baud_rate": 9600, 9 | "parity": "N", 10 | "data_bits": 8, 11 | "stop_bits": 1, 12 | "enabled": true, 13 | "devices" : [ 14 | { 15 | "slave_id": "255", 16 | "device_type": "milur305" 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/configs/config-modbus-io-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "max_unchanged_interval": 100, 4 | "ports": [ 5 | { 6 | "path" : "/dev/ttyNSC0", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 1, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "slave_id": "1:1", 15 | "device_type" : "ModbusI-test-device", 16 | "name": "ModbusIO_1_1", 17 | "id": "modbus-io-1-1", 18 | "frame_timeout_ms": 0, 19 | "response_timeout_ms": 8 20 | }, 21 | { 22 | "slave_id": "1:2", 23 | "device_type" : "ModbusO-test-device", 24 | "name": "ModbusIO_1_2", 25 | "id": "modbus-io-1-2", 26 | "frame_timeout_ms": 0, 27 | "response_timeout_ms": 8 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /test/configs/config-modbus-publish-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "ports": [ 4 | { 5 | "path": "/dev/ttyNSC0", 6 | "baud_rate": 9600, 7 | "parity": "N", 8 | "data_bits": 8, 9 | "stop_bits": 1, 10 | "enabled": true, 11 | "devices": [ 12 | { 13 | "slave_id": 1, 14 | "enabled": true, 15 | "name": "Modbus-sample", 16 | "id": "modbus-sample", 17 | "channels": [ 18 | { 19 | "name": "Normal Channel", 20 | "reg_type": "input", 21 | "address": 23, 22 | "type": "value", 23 | "format": "u16", 24 | "sporadic": false 25 | }, 26 | { 27 | "name": "Sporadic Channel", 28 | "reg_type": "input", 29 | "address": 42, 30 | "type": "value", 31 | "format": "u16", 32 | "sporadic": true 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /test/configs/config-modbus-reconnect.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "baud_rate": 9600, 7 | "parity": "N", 8 | "data_bits": 8, 9 | "stop_bits": 1, 10 | "enabled": true, 11 | "devices" : [ 12 | { 13 | "slave_id": 1, 14 | "enabled": true, 15 | "name": "Modbus", 16 | "id": "modbus", 17 | "max_read_registers": 0, 18 | "frame_timeout_ms": 0, 19 | "device_timeout_ms": 1, 20 | "device_max_fail_cycles": 1, 21 | "setup": [ 22 | { 23 | "title": "Set", 24 | "address": 94, 25 | "value": "0x0F41" 26 | } 27 | ], 28 | "channels": [ 29 | { 30 | "name" : "Ch 0", 31 | "reg_type" : "holding", 32 | "address" : 70 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /test/configs/config-no-collision-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": true, 3 | "max_unchanged_interval": 100, 4 | "ports": [ 5 | { 6 | "path" : "/dev/ttyAPP0", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 1, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "slave_id": "255", 15 | "name": "Device", 16 | "id": "device1", 17 | "enabled": true, 18 | "max_read_registers": 0, 19 | "protocol": "modbus", 20 | "channels": [ 21 | { 22 | "name": "Channel", 23 | "reg_type": "holding", 24 | "address": 0 25 | } 26 | ] 27 | } 28 | ] 29 | }, 30 | { 31 | "path" : "/dev/ttyAPP1", 32 | "baud_rate": 9600, 33 | "parity": "N", 34 | "data_bits": 8, 35 | "stop_bits": 1, 36 | "enabled": true, 37 | "devices" : [ 38 | { 39 | "slave_id": "255", 40 | "name": "Device", 41 | "id": "device2", 42 | "enabled": true, 43 | "max_read_registers": 0, 44 | "protocol": "modbus", 45 | "channels": [ 46 | { 47 | "name": "Channel", 48 | "reg_type": "holding", 49 | "address": 0 50 | } 51 | ] 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /test/configs/config-uniel-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "port_type" : "serial", 6 | "path" : "/dev/ttyNSC1", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 1, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "name": "PseudoUniel", 15 | "id": "pseudo_uniel", 16 | "slave_id": 1, 17 | "enabled": true, 18 | "protocol": "uniel", 19 | "frame_timeout_ms": 100, 20 | "channels": [ 21 | { 22 | "name": "Input 0", 23 | "reg_type": "input", 24 | "address": "0x0a" 25 | }, 26 | { 27 | "name" : "Relay 1", 28 | "reg_type": "relay", 29 | "address": "0x1b" 30 | }, 31 | { 32 | "name": "LowThr", 33 | "reg_type": "param", 34 | "address": "0x02", 35 | "type": "range", 36 | "max": "0xff" 37 | }, 38 | { 39 | "name" : "LED 1", 40 | "reg_type": "brightness", 41 | "address": "0x141", 42 | "type": "range", 43 | "max": "0xff" 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /test/configs/parse_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "port_type" : "serial", 6 | "path" : "/dev/ttyAPP1", 7 | "baud_rate": 9600, 8 | "parity": "N", 9 | "data_bits": 8, 10 | "stop_bits": 1, 11 | "enabled": true, 12 | "devices" : [ 13 | { 14 | "name": "PseudoS2K", 15 | "id": "pseudo_s2k", 16 | "slave_id": 1, 17 | "enabled": true, 18 | "protocol": "s2k", 19 | "frame_timeout_ms": 100, 20 | "channels": [ 21 | { 22 | "name": "Relay default 1", 23 | "reg_type": "relay_default", 24 | "address": "0x01", 25 | "enum": [0, 1], 26 | "enum_titles": ["zero", "one"], 27 | "format": "u8" 28 | }, 29 | { 30 | "name": "Relay default 2", 31 | "reg_type": "relay_default", 32 | "address": "0x02", 33 | "enum": ["2", "3"], 34 | "enum_titles": ["two", "three"], 35 | "format": "u8" 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /test/configs/parse_test_parameters_array.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "parameters array", 9 | "slave_id": 2, 10 | "p1": 1, 11 | "p2": 3 12 | } 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /test/configs/parse_test_readonly_parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "readonly parameters", 9 | "slave_id": 2, 10 | "p1": 1, 11 | "p2": 3, 12 | "p3": 2 13 | } 14 | ] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /test/configs/parse_test_setup.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "with setup", 9 | "slave_id": 2, 10 | "setup": [ 11 | { 12 | "title" : "s2 override", 13 | "address": 9992, 14 | "value": 100 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/configs/parse_test_setup_condition.json: -------------------------------------------------------------------------------- 1 | { 2 | "ports": [ 3 | { 4 | "path" : "/dev/ttyNSC0", 5 | "devices" : [ 6 | { 7 | "device_type" : "setup with condition", 8 | "slave_id": 1 9 | }, 10 | { 11 | "device_type" : "setup with condition", 12 | "slave_id": 2, 13 | "p1": 1 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /test/configs/reconnect_test_ebadf.json: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "baud_rate": 9600, 7 | "parity": "N", 8 | "data_bits": 8, 9 | "stop_bits": 1, 10 | "connection_timeout_ms" : 500, 11 | "connection_max_fail_cycles": 2, 12 | "devices" : [ 13 | { 14 | "name": "Test", 15 | "id": "test", 16 | "slave_id": 1, 17 | "setup": [ 18 | { 19 | "title": "Input 1", 20 | "address": 1, 21 | "value": 42 22 | } 23 | ], 24 | "channels": [ 25 | { 26 | "name": "I1", 27 | "address": "0x01" 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /test/configs/reconnect_test_network.json: -------------------------------------------------------------------------------- 1 | { 2 | "ports": [ 3 | { 4 | "path" : "/dev/ttyNSC0", 5 | "baud_rate": 9600, 6 | "parity": "N", 7 | "data_bits": 8, 8 | "stop_bits": 1, 9 | "connection_timeout_ms" : 70, 10 | "connection_max_fail_cycles": 2, 11 | "devices" : [ 12 | { 13 | "name": "Reconnect test", 14 | "id": "reconnect-test", 15 | "slave_id": 12, 16 | "protocol": "fake", 17 | "device_timeout_ms": 50, 18 | "device_max_fail_cycles": 2, 19 | "channels": [ 20 | { 21 | "name": "I1", 22 | "reg_type": "fake", 23 | "address": "0x01", 24 | "format": "u8", 25 | "type": "value", 26 | "scale": 0.001 27 | } 28 | ] 29 | } 30 | ] 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-0.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "name": "ErrorValueTest", 9 | "id": "ErrorValueTest", 10 | "slave_id": "0x91", 11 | "channels": [ 12 | { 13 | "name" : "negative-int", 14 | "reg_type" : "holding", 15 | "address" : "0x00", 16 | "type": "switch", 17 | "error_value" : -4 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "ports": [ 3 | { 4 | "path" : "/dev/ttyNSC0", 5 | "devices" : [ 6 | { 7 | "name": "ErrorValueTest", 8 | "id": "ErrorValueTest", 9 | "slave_id": "0x91", 10 | "channels": [ 11 | { 12 | "name" : "negative-int-str", 13 | "reg_type" : "holding", 14 | "address" : "0x00", 15 | "type": "switch", 16 | "error_value" : "-4" 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-10.json: -------------------------------------------------------------------------------- 1 | // missing manadotory subdevice parameter 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "subdevice", 9 | "slave_id": 2, 10 | "channels": 11 | [ 12 | { 13 | "name" : "Sub2", 14 | "device_type" : "subdevice3" 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-11.json: -------------------------------------------------------------------------------- 1 | // missing required param1 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "baud_rate": 9600, 7 | "parity": "N", 8 | "data_bits": 8, 9 | "stop_bits": 2, 10 | "devices" : [ 11 | { 12 | "slave_id": 22, 13 | "device_type": "with conditions" 14 | }, 15 | { 16 | "slave_id": 23, 17 | "device_type": "with conditions", 18 | "param1": 1 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-12.json: -------------------------------------------------------------------------------- 1 | // param3 in second device has not allowed value 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "baud_rate": 9600, 7 | "parity": "N", 8 | "data_bits": 8, 9 | "stop_bits": 2, 10 | "devices" : [ 11 | { 12 | "slave_id": 22, 13 | "device_type": "with conditions", 14 | "param1": 2, 15 | "param3": 11 16 | }, 17 | { 18 | "slave_id": 23, 19 | "device_type": "with conditions", 20 | "param1": 2, 21 | "param3": 1 22 | } 23 | ] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-13.json: -------------------------------------------------------------------------------- 1 | // duplicate definition of param4 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "baud_rate": 9600, 7 | "parity": "N", 8 | "data_bits": 8, 9 | "stop_bits": 2, 10 | "devices" : [ 11 | { 12 | "slave_id": 22, 13 | "device_type": "with duplicate params", 14 | "param1": 4 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "ports": [ 3 | { 4 | "path" : "/dev/ttyNSC0", 5 | "devices" : [ 6 | { 7 | "name": "ErrorValueTest", 8 | "id": "ErrorValueTest", 9 | "slave_id": "0x91", 10 | "channels": [ 11 | { 12 | "name" : "random-text", 13 | "reg_type" : "holding", 14 | "address" : "0x00", 15 | "type": "switch", 16 | "error_value" : "blah" 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "ports": [ 3 | { 4 | "path" : "/dev/ttyNSC0", 5 | "devices" : [ 6 | { 7 | "name": "ErrorValueTest", 8 | "id": "ErrorValueTest", 9 | "slave_id": "0x91", 10 | "channels": [ 11 | { 12 | "name" : "int32-overflow", 13 | "reg_type" : "holding", 14 | "address" : "0x00", 15 | "type": "switch", 16 | "error_value" : 4294967296 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-4.json: -------------------------------------------------------------------------------- 1 | // wrong channel's device_type 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "subdevice", 9 | "slave_id": 2, 10 | "channels": 11 | [ 12 | { 13 | "name" : "Sub1", 14 | "device_type" : "subdevice2" 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-5.json: -------------------------------------------------------------------------------- 1 | // wrong channel's device_type 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "subdevice", 9 | "slave_id": 2, 10 | "channels": 11 | [ 12 | { 13 | "name" : "Sub2", 14 | "device_type" : "subdevice3" 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-6.json: -------------------------------------------------------------------------------- 1 | // setup command without value 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "subdevice", 9 | "slave_id": 2, 10 | "channels": 11 | [ 12 | { 13 | "name" : "Sub1", 14 | "device_type" : "subdevice1", 15 | "setup": [ 16 | { 17 | "title": "bad", 18 | "address": 10 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-7.json: -------------------------------------------------------------------------------- 1 | // setup command without address 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "subdevice", 9 | "slave_id": 2, 10 | "channels": 11 | [ 12 | { 13 | "name" : "Sub1", 14 | "device_type" : "subdevice1", 15 | "setup": [ 16 | { 17 | "title": "bad", 18 | "value": 10 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-8.json: -------------------------------------------------------------------------------- 1 | // channel without device_type 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "subdevice", 9 | "slave_id": 2, 10 | "channels": 11 | [ 12 | { 13 | "name" : "Sub2", 14 | "setup": [ 15 | { 16 | "title": "bad", 17 | "value": 10 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /test/configs/unsuccessful/unsuccessful-9.json: -------------------------------------------------------------------------------- 1 | // channel with device_type, but in template it is without device_type 2 | { 3 | "ports": [ 4 | { 5 | "path" : "/dev/ttyNSC0", 6 | "devices" : [ 7 | { 8 | "device_type" : "subdevice", 9 | "slave_id": 2, 10 | "channels": 11 | [ 12 | { 13 | "name" : "Sub1", 14 | "device_type" : "subdevice1", 15 | "channels": [ 16 | { 17 | "name": "c11", 18 | "device_type" : "subdevice1" 19 | } 20 | ] 21 | } 22 | ] 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /test/device-templates/config-invalid-channel-condition.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "invalid_channel_condition", 3 | "device": { 4 | "name": "invalid channel condition", 5 | "id": "invalid channel condition", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504", 12 | "condition": "( in1 > 3 )" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/device-templates/config-invalid-param-condition.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "invalid_param_condition", 3 | "device": { 4 | "name": "invalid param condition", 5 | "id": "invalid param condition", 6 | "setup": [ 7 | { 8 | "title": "Param", 9 | "address": "0x0504", 10 | "value": 1 11 | } 12 | ], 13 | "channels": [ 14 | { 15 | "name": "Temperature", 16 | "reg_type": "input", 17 | "format": "s32", 18 | "address": "0x0504" 19 | } 20 | ], 21 | "parameters": [ 22 | { 23 | "id": "Test", 24 | "title": "p1", 25 | "address": 9992, 26 | "condition": "( in1 > 3 )" 27 | } 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/device-templates/config-invalid-setup-condition.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "invalid_setup_condition", 3 | "device": { 4 | "name": "invalid setup condition", 5 | "id": "invalid setup condition", 6 | "setup": [ 7 | { 8 | "title": "Param", 9 | "address": "0x0504", 10 | "value": 1, 11 | "condition": "( in1 > 3 )" 12 | } 13 | ], 14 | "channels": [ 15 | { 16 | "name": "Temperature", 17 | "reg_type": "input", 18 | "format": "s32", 19 | "address": "0x0504" 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/device-templates/config-modbus-i.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "ModbusI-test-device", 3 | "device": { 4 | "protocol": "modbus_io", 5 | "stride": 1000, 6 | "max_read_registers": 0, 7 | "setup": [ 8 | { 9 | "title": "IODIR", 10 | "address": 9999, 11 | "value": "0xffff" 12 | }, 13 | { 14 | "title": "CONFIG-FLAG", 15 | "address": 10000, 16 | "value": 1 17 | } 18 | ], 19 | "channels": [ 20 | { 21 | "name" : "Coil 0", 22 | "reg_type" : "coil", 23 | "address" : 0, 24 | "type" : "switch" 25 | }, 26 | { 27 | "name" : "Input 1", 28 | "reg_type" : "coil", 29 | "readonly" : true, 30 | "address" : 1, 31 | "type" : "switch" 32 | }, 33 | { 34 | "name" : "Input 2", 35 | "reg_type" : "coil", 36 | "readonly" : true, 37 | "address" : 2, 38 | "type" : "switch" 39 | } 40 | ] 41 | } 42 | } -------------------------------------------------------------------------------- /test/device-templates/config-modbus-o.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "ModbusO-test-device", 3 | "device": { 4 | "protocol": "modbus_io", 5 | "stride": 1000, 6 | "shift": 500, 7 | "max_read_registers": 0, 8 | "setup": [ 9 | { 10 | "title": "IODIR", 11 | "address": 9999, 12 | "value": "0xffff" 13 | }, 14 | { 15 | "title": "CONFIG-FLAG", 16 | "address": 10000, 17 | "value": 1 18 | } 19 | ], 20 | "channels": [ 21 | { 22 | "name" : "Coil 0", 23 | "reg_type" : "coil", 24 | "address" : 0, 25 | "type" : "switch" 26 | }, 27 | { 28 | "name" : "Input 1", 29 | "reg_type" : "coil", 30 | "readonly" : true, 31 | "address" : 1, 32 | "type" : "switch" 33 | }, 34 | { 35 | "name" : "Input 2", 36 | "reg_type" : "coil", 37 | "readonly" : true, 38 | "address" : 2, 39 | "type" : "switch" 40 | } 41 | ] 42 | } 43 | } -------------------------------------------------------------------------------- /test/device-templates/config-msu34.json: -------------------------------------------------------------------------------- 1 | // Configuration options 2 | { 3 | "device_type" : "MSU34", 4 | "device" : { 5 | "name": "MSU34+TLP", 6 | "id": "msu34tlp", 7 | "enabled": true, 8 | "guard_interval_us": 20000, 9 | "channels": [ 10 | { 11 | "name" : "Temp 1", 12 | "reg_type" : "input", 13 | "address" : 0, 14 | "type": "temperature", 15 | "format": "s8" 16 | }, 17 | { 18 | "name" : "Illuminance", 19 | "reg_type" : "input", 20 | "address" : 1, 21 | "type": "lux" 22 | }, 23 | { 24 | "name" : "Pressure", 25 | "reg_type" : "input", 26 | "address" : 2, 27 | "type": "pressure", 28 | "scale": 0.075 29 | }, 30 | { 31 | "name" : "Temp 2", 32 | "reg_type" : "input", 33 | "address" : 3, 34 | "type": "temperature", 35 | "format": "s8" 36 | } 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/device-templates/config-msu34.json.wrong: -------------------------------------------------------------------------------- 1 | // Configuration options 2 | { 3 | "device_type" : "MSU34_BAD", 4 | "device" : { 5 | "name": "MSU34+TLP_BAD", 6 | "id": "msu34tlp-bad", 7 | "enabled": true, 8 | "guard_interval_us": 20000, 9 | "channels": [ 10 | { 11 | "name" : "Temp 1", 12 | "reg_type" : "input", 13 | "address" : 0, 14 | "type": "temperature", 15 | "format": "s8" 16 | }, 17 | { 18 | "name" : "Illuminance", 19 | "reg_type" : "input", 20 | "address" : 1, 21 | "type": "lux" 22 | }, 23 | { 24 | "name" : "Pressure", 25 | "reg_type" : "input", 26 | "address" : 2, 27 | "type": "pressure", 28 | "scale": 0.075 29 | }, 30 | { 31 | "name" : "Temp 2", 32 | "reg_type" : "input", 33 | "address" : 3, 34 | "type": "temperature", 35 | "format": "s8" 36 | } 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/device-templates/config-parameters-array-invalid-address.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "parameters_array_invalid_address", 3 | "device": { 4 | "name": "parameters array invalid address", 5 | "id": "parameters array invalid address", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters": [ 15 | { 16 | "id": "p1", 17 | "title": "p1", 18 | "address": 9992 19 | }, 20 | { 21 | "id": "p2", 22 | "title": "p2", 23 | "address": 9996, 24 | "condition": "p1==0" 25 | }, 26 | { 27 | "id": "p2", 28 | "title": "p2", 29 | "address": 9997, 30 | "condition": "p1==1" 31 | } 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/device-templates/config-parameters-array-invalid-id.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "parameters_array_invalid_id", 3 | "device": { 4 | "name": "parameters array invalid id", 5 | "id": "parameters array invalid id", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters": [ 15 | { 16 | "id": "test 123", 17 | "title": "p1", 18 | "address": 9992 19 | } 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/device-templates/config-parameters-array.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "parameters array", 3 | "device": { 4 | "name": "parameters array", 5 | "id": "parameters array", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters": [ 15 | { 16 | "id": "p1", 17 | "title": "p1", 18 | "address": 9992 19 | }, 20 | { 21 | "id": "p2", 22 | "title": "p2", 23 | "address": 9996, 24 | "condition": "p1==0" 25 | }, 26 | { 27 | "id": "p2", 28 | "title": "p2", 29 | "address": 9996, 30 | "condition": "p1==1" 31 | } 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/device-templates/config-parameters-object-invalid-name-deprecated.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "parameters_object_invalid_name", 3 | "deprecated": true, 4 | "device": { 5 | "name": "parameters object invalid name", 6 | "id": "parameters object invalid name", 7 | "channels": [ 8 | { 9 | "name": "Temperature", 10 | "reg_type": "input", 11 | "format": "s32", 12 | "address": "0x0504" 13 | } 14 | ], 15 | "parameters": { 16 | "123test": { 17 | "title": "p1", 18 | "address": 9992 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/device-templates/config-parameters-object-invalid-name.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "tpl1_parameters_object_invalid_name", 3 | "device": { 4 | "name": "parameters object invalid name", 5 | "id": "parameters object invalid name", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters": { 15 | "123test": { 16 | "title": "p1", 17 | "address": 9992 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/device-templates/config-readonly-parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "readonly parameters", 3 | "device": { 4 | "name": "readonly parameters", 5 | "id": "readonly parameters", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters": [ 15 | { 16 | "id": "p1", 17 | "title": "p1", 18 | "readonly": true 19 | }, 20 | { 21 | "id": "p2", 22 | "title": "p2", 23 | "address": 9996, 24 | "condition": "p1==1" 25 | }, 26 | { 27 | "id": "p3", 28 | "title": "p3", 29 | "address": 9997, 30 | "condition": "p1==0" 31 | }, 32 | { 33 | "id": "p4", 34 | "title": "p4", 35 | "readonly": true, 36 | "address": 12345 37 | } 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/device-templates/config-setup-items-with-condition.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "setup with condition", 3 | "device": { 4 | "name": "setup with condition", 5 | "id": "setup with condition", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters": [ 15 | { 16 | "id": "p1", 17 | "title": "p1", 18 | "address": 9993 19 | } 20 | ], 21 | "setup": [ 22 | { 23 | "title": "s2", 24 | "address": 9992, 25 | "value": "0xfff2", 26 | "condition": "p1==1" 27 | }, 28 | { 29 | "title": "s3", 30 | "address": 9995, 31 | "value": 10, 32 | "scale": 2 33 | } 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/device-templates/config-setup-items.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "with setup", 3 | "device": { 4 | "name": "with setup", 5 | "id": "with setup", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "setup": [ 15 | { 16 | "title": "s2", 17 | "address": 9992, 18 | "value": "0xfff2" 19 | }, 20 | { 21 | "title": "s3", 22 | "address": 9995, 23 | "value": 10, 24 | "scale": 2 25 | } 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/device-templates/test-device-override.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "TestDeviceOverride", 3 | "device": { 4 | "name": "TestDeviceOverride:template", 5 | "id": "TestDeviceOverride:template", 6 | "max_reg_hole" : 1, 7 | "max_bit_hole" : 1, 8 | "channels": [ 9 | { 10 | "name": "Chan 1", 11 | "reg_type": "input", 12 | "address": 0, 13 | "type": "temperature", 14 | "format": "s8" 15 | } 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /test/device-templates/test-device-override2.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "TestDeviceOverride2", 3 | "device": { 4 | "name": "TestDeviceOverride2:template", 5 | "id": "TestDeviceOverride2:template", 6 | "protocol": "modbus", 7 | "channels": [ 8 | { 9 | "name": "Input", 10 | "reg_type": "input", 11 | "address": 0 12 | }, 13 | { 14 | "name": "Holding", 15 | "reg_type": "holding", 16 | "address": 1 17 | }, 18 | { 19 | "name": "Holding readonly", 20 | "reg_type": "holding", 21 | "address": 2, 22 | "readonly": true 23 | } 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_array_match_values.json: -------------------------------------------------------------------------------- 1 | // result data for "parameters_array" template conditions test 2 | { 3 | "p1": 1, 4 | "p2": 12 5 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_array_read_values.json: -------------------------------------------------------------------------------- 1 | // fake read values for "parameters_array" template conditions test 2 | { 3 | "p1": 1, 4 | "p2": 12, 5 | "p3": 1, 6 | "p4": 42 7 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_array_register_list.json: -------------------------------------------------------------------------------- 1 | // matching data for "parameters_array" register list test 2 | { 3 | "p1": 1001, 4 | "p2": 1002, 5 | "p3": 1003, 6 | "p4": 1004 7 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_group_array_register_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "p1": 1001, 3 | "p2": 1002, 4 | "p4": 1004, 5 | "p5": 1005, 6 | "p7": 1007 7 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_group_object_register_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "p1": 2001, 3 | "p5": 2005, 4 | "p6": 2006, 5 | "p7": 2007 6 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_object_match_values.json: -------------------------------------------------------------------------------- 1 | // result data for "parameters_object" template conditions test 2 | { 3 | "p1": 0, 4 | "p5": 1, 5 | "p7": 42 6 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_object_read_values.json: -------------------------------------------------------------------------------- 1 | // fake read values for "parameters_object" template conditions test 2 | { 3 | "p1": 0, 4 | "p3": 22, 5 | "p5": 1, 6 | "p7": 42 7 | } -------------------------------------------------------------------------------- /test/device_load_config_test/parameters_object_register_list.json: -------------------------------------------------------------------------------- 1 | // result data for "parameters_object" register list test 2 | { 3 | "p1": 2001, 4 | "p3": 2003, 5 | "p5": 2005, 6 | "p7": 2007 7 | } -------------------------------------------------------------------------------- /test/energomera_test.cpp: -------------------------------------------------------------------------------- 1 | #include "devices/energomera_iec_device.h" 2 | #include "fake_serial_port.h" 3 | #include 4 | 5 | namespace 6 | { 7 | class TEnergomeraIntegrationTest: public TSerialDeviceIntegrationTest, public virtual TExpectorProvider 8 | { 9 | protected: 10 | const char* ConfigPath() const override 11 | { 12 | return "configs/config-energomera-test.json"; 13 | } 14 | 15 | void EnqueuePollRequests() 16 | { 17 | Expector()->Expect( 18 | ExpectVectorFromString("/?00000211!\x01R1\x02GROUP(400B(7)400D(1)5003(1))\x03\x68"), 19 | ExpectVectorFromString("\x02" 20 | "400B(E12)(118.8)(121.1)400D(50.01)5003(009114135064195)\x03\x1e"), 21 | __func__); 22 | } 23 | }; 24 | } 25 | 26 | TEST_F(TEnergomeraIntegrationTest, Poll) 27 | { 28 | EnqueuePollRequests(); 29 | Note() << "LoopOnce()"; 30 | SerialDriver->LoopOnce(); 31 | } 32 | -------------------------------------------------------------------------------- /test/expector.cpp: -------------------------------------------------------------------------------- 1 | #include "expector.h" 2 | #include 3 | 4 | std::vector ExpectVectorFromString(const std::string& str) 5 | { 6 | std::vector res(str.begin(), str.end()); 7 | return res; 8 | } -------------------------------------------------------------------------------- /test/expector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class TExpector 6 | { 7 | public: 8 | virtual ~TExpector() = default; 9 | virtual void Expect(const std::vector& request, const std::vector& response, const char* func = 0) = 0; 10 | }; 11 | 12 | typedef std::shared_ptr PExpector; 13 | 14 | class TExpectorProvider 15 | { 16 | public: 17 | virtual ~TExpectorProvider() = default; 18 | virtual PExpector Expector() const = 0; 19 | }; 20 | 21 | std::vector ExpectVectorFromString(const std::string& str); -------------------------------------------------------------------------------- /test/expressions/bad.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | a== 4 | ||1 5 | a~=1 6 | 1a==3 7 | (a==1 8 | a==3) 9 | a&&(b<7 10 | a&&b<7) 11 | (a==1)1 12 | (a==1)b 13 | (a==1)(1==c) 14 | b(a==1) 15 | 1(a==1) 16 | isDefined() 17 | isDefined(a 18 | isDefined(a==1) 19 | isDefined(1) 20 | (isDefined(a) 21 | isDefined(a)) 22 | -------------------------------------------------------------------------------- /test/expressions/good.txt: -------------------------------------------------------------------------------- 1 | a 2 | 1 3 | (a) 4 | (1) 5 | ((a)) 6 | ((1)) 7 | a==1 8 | (a==1) 9 | ((a==1)) 10 | 1==2 11 | 1==a 12 | a!=1 13 | a>1 14 | a<1 15 | a>=1 16 | a<=1 17 | a||1 18 | a&&1 19 | (a==1)&&1 20 | (a==1)&&b 21 | (a==1)&&(b==2) 22 | ((a==1)&&1) 23 | 1==(a&&2) 24 | a==1&&2 25 | a==1&&b==3 26 | a==1&&b==3||c<4||c>5 27 | a==1&&b==3||(c<4||c>5) 28 | (a==1)&&(b==3)||(c<4) 29 | (a==1)&&(b==3)||(c<4)||(d!=5) 30 | (a==1)&&((b==3)||(c<4))||(d!=5) 31 | isDefined(a) 32 | isDefined(a)&&isDefined(b) 33 | a==1&&isDefined(a) 34 | a==1&&(isDefined(a)) 35 | a==1&&isDefined(a)||b==3&&isDefined(b) 36 | a==1&&(isDefined(a)||b==3&&isDefined(b)) 37 | (isDefined(in1_mode)==0||in1_mode==0)==0 38 | -------------------------------------------------------------------------------- /test/hw-templates/hw.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "with hw", 3 | "title": "with hw", 4 | "hw" : [ 5 | { 6 | "signature": "signature" 7 | }, 8 | { 9 | "signature": "signature2", 10 | "fw": "1.1.1" 11 | } 12 | ], 13 | "device": { 14 | "name": "with hw", 15 | "id": "with hw", 16 | "channels": [ 17 | { 18 | "name": "temperature", 19 | "reg_type": "input", 20 | "format": "s32", 21 | "address": "0x0504" 22 | } 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using WBMQTT::Testing::TLoggedFixture; 8 | 9 | void ParseCommadLine(int argc, char** argv) 10 | { 11 | int debugLevel = 0; 12 | int c; 13 | 14 | while ((c = getopt(argc, argv, "d:")) != -1) { 15 | if (c == 'd') { 16 | debugLevel = std::atoi(optarg); 17 | } 18 | } 19 | 20 | switch (debugLevel) { 21 | case 1: 22 | Debug.SetEnabled(true); 23 | break; 24 | 25 | case 2: 26 | WBMQTT::Debug.SetEnabled(true); 27 | break; 28 | 29 | case 3: 30 | WBMQTT::Debug.SetEnabled(true); 31 | Debug.SetEnabled(true); 32 | break; 33 | 34 | default: 35 | break; 36 | } 37 | } 38 | 39 | int main(int argc, char** argv) 40 | { 41 | WBMQTT::SetThreadName(argv[0]); 42 | TLoggedFixture::SetExecutableName(argv[0]); 43 | ::testing::InitGoogleTest(&argc, argv); 44 | ParseCommadLine(argc, argv); 45 | return RUN_ALL_TESTS(); 46 | } 47 | -------------------------------------------------------------------------------- /test/mercury200_expectations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "expector.h" 3 | 4 | class TMercury200Expectations: public virtual TExpectorProvider 5 | { 6 | public: 7 | void EnqueueMercury200EnergyResponse(); 8 | void EnqueueMercury200ParamResponse(); 9 | void EnqueueMercury200BatteryVoltageResponse(); 10 | }; 11 | -------------------------------------------------------------------------------- /test/milur_expectations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "expector.h" 3 | 4 | class TMilurExpectations: public virtual TExpectorProvider 5 | { 6 | public: 7 | void EnqueueMilurIgnoredPacketWorkaround(); 8 | void EnqueueMilurSessionSetupResponse(); 9 | void EnqueueMilur32SessionSetupResponse(); 10 | void EnqueueMilurAccessLevel2SessionSetupResponse(); 11 | 12 | void EnqueueMilurPhaseAVoltageResponse(); 13 | void EnqueueMilurPhaseBVoltageResponse(); 14 | void EnqueueMilurPhaseCVoltageResponse(); 15 | 16 | void EnqueueMilurPhaseACurrentResponse(); 17 | void EnqueueMilurPhaseBCurrentResponse(); 18 | void EnqueueMilurPhaseCCurrentResponse(); 19 | 20 | void EnqueueMilurPhaseAActivePowerResponse(); 21 | void EnqueueMilurPhaseBActivePowerResponse(); 22 | void EnqueueMilurPhaseCActivePowerResponse(); 23 | void EnqueueMilurTotalActivePowerResponse(); 24 | 25 | void EnqueueMilurPhaseAReactivePowerResponse(); 26 | void EnqueueMilurPhaseBReactivePowerResponse(); 27 | void EnqueueMilurPhaseCReactivePowerResponse(); 28 | void EnqueueMilurTotalReactivePowerResponse(); 29 | 30 | void EnqueueMilurTotalConsumptionResponse(); 31 | void EnqueueMilurTotalReactiveEnergyResponse(); 32 | 33 | void EnqueueMilurFrequencyResponse(); 34 | 35 | void EnqueueMilur32TotalConsumptionResponse(); 36 | void EnqueueMilurNoSessionResponse(); 37 | void EnqueueMilurExceptionResponse(); 38 | }; 39 | -------------------------------------------------------------------------------- /test/modbus_expectations_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "expector.h" 4 | 5 | #include 6 | 7 | class TModbusExpectationsBase: public virtual TExpectorProvider 8 | { 9 | protected: 10 | enum ModbusType 11 | { 12 | MODBUS_RTU 13 | }; 14 | 15 | ModbusType GetSelectedModbusType() const; 16 | void SelectModbusType(ModbusType selectedModbusType); 17 | 18 | uint8_t GetModbusRTUSlaveId() const; 19 | void SetModbusRTUSlaveId(uint8_t slaveId); 20 | 21 | std::vector WrapPDU(const std::vector& pdu, uint8_t slaveId); 22 | std::vector WrapPDU(const std::vector& pdu); 23 | 24 | private: 25 | ModbusType SelectedModbusType = MODBUS_RTU; 26 | uint8_t RtuSlaveId = 1; 27 | }; 28 | -------------------------------------------------------------------------------- /test/modbus_io_expectations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "modbus_expectations_base.h" 4 | 5 | class TModbusIOExpectations: public TModbusExpectationsBase 6 | { 7 | public: 8 | void EnqueueSetupSectionWriteResponse(bool firstModule, bool error = false); 9 | void EnqueueCoilReadResponse(bool firstModule); 10 | void EnqueueCoilWriteResponse(bool firstModule); 11 | }; 12 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok1.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type" : "merge simple", 3 | "slave_id": 2 4 | } 5 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok10.json: -------------------------------------------------------------------------------- 1 | // device template with conditions and defined parameters 2 | { 3 | "device_type" : "merge condition", 4 | "slave_id": 2, 5 | "param1": 1, 6 | "param3": 3 7 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok11.json: -------------------------------------------------------------------------------- 1 | // device template with conditions and defined parameters 2 | { 3 | "device_type" : "merge condition", 4 | "slave_id": 2, 5 | "param1": 2, 6 | "param2": 3 7 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok12.json: -------------------------------------------------------------------------------- 1 | // device template with conditions and too many parameters 2 | { 3 | "device_type" : "merge condition", 4 | "slave_id": 2, 5 | "param1": 2, 6 | "param3": 3 7 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok13.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type" : "with conditions", 3 | "slave_id": 2, 4 | "param1": 1, 5 | "param2": 2 6 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok2.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type" : "merge simple with setup", 3 | "slave_id": 2 4 | } 5 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok3.json: -------------------------------------------------------------------------------- 1 | // additional channels and setup registers, parameters overriding 2 | { 3 | "device_type" : "merge simple with setup", 4 | "slave_id": 2, 5 | "channels" : 6 | [ 7 | { 8 | "address" : "0x0506", 9 | "format" : "s32", 10 | "name" : "New channel", 11 | "reg_type" : "input" 12 | } 13 | ], 14 | "id" : "1", 15 | "name" : "2", 16 | "setup" : 17 | [ 18 | { 19 | "address" : 50000, 20 | "title" : "new setup", 21 | "value" : "0xffff" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok4.json: -------------------------------------------------------------------------------- 1 | // additional channels and setup registers, parameters overriding 2 | { 3 | "device_type" : "merge subdevice", 4 | "slave_id": 2 5 | } 6 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok5.json: -------------------------------------------------------------------------------- 1 | // additional channels and setup registers, parameters overriding 2 | { 3 | "device_type" : "merge subdevice", 4 | "slave_id": 2, 5 | "channels" : 6 | [ 7 | { 8 | "name" : "Sub", 9 | "device_type" : "subdevice1", 10 | "channels" : 11 | [ 12 | { 13 | "name" : "c1", 14 | "poll_interval" : 100 15 | }, 16 | { 17 | "enabled" : false, 18 | "name" : "c2" 19 | } 20 | ], 21 | "setup" : 22 | [ 23 | { 24 | "address" : 20000, 25 | "title" : "31", 26 | "value" : "0xffff" 27 | } 28 | ] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok6.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type" : "merge subdevice2", 3 | "slave_id": 2 4 | } 5 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok7.json: -------------------------------------------------------------------------------- 1 | // additional channels and setup registers, parameters overriding in subsubdevice 2 | { 3 | "device_type" : "merge subdevice2", 4 | "slave_id": 2, 5 | "channels" : 6 | [ 7 | { 8 | "name" : "Sub", 9 | "device_type" : "subdevice1", 10 | "channels" : 11 | [ 12 | { 13 | "name" : "c2", 14 | "device_type" : "subdevice2", 15 | "channels" : 16 | [ 17 | { 18 | "name" : "c12", 19 | "read_period_ms" : 100 20 | }, 21 | { 22 | "enabled" : false, 23 | "name" : "c22" 24 | } 25 | ], 26 | "setup" : 27 | [ 28 | { 29 | "address" : 25000, 30 | "title" : "31", 31 | "value" : "0xffff" 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok8.json: -------------------------------------------------------------------------------- 1 | // device template with conditions 2 | { 3 | "device_type" : "merge condition", 4 | "slave_id": 2 5 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_ok9.json: -------------------------------------------------------------------------------- 1 | // device template with conditions and defined parameter 2 | { 3 | "device_type" : "merge condition", 4 | "slave_id": 2, 5 | "param1": 1 6 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_res1.json: -------------------------------------------------------------------------------- 1 | { 2 | "channels" : 3 | [ 4 | { 5 | "address" : "0x0500", 6 | "format" : "s32", 7 | "name" : "Voltage", 8 | "reg_type" : "input" 9 | }, 10 | { 11 | "address" : "0x0504", 12 | "format" : "s32", 13 | "name" : "Temperature", 14 | "reg_type" : "input" 15 | } 16 | ], 17 | "device_type" : "merge simple", 18 | "id" : "merge-simple_2", 19 | "name" : "merge simple 2", 20 | "slave_id" : 2 21 | } 22 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_res10.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "merge condition", 3 | "id": "merge-condition_2", 4 | "name": "merge condition 2", 5 | "slave_id": 2, 6 | "channels": 7 | [ 8 | { 9 | "address": "0x0501", 10 | "name": "c1" 11 | }, 12 | { 13 | "address" : "0x0502", 14 | "condition" : "param1==1", 15 | "name" : "c2" 16 | }, 17 | { 18 | "address" : "0x0503", 19 | "condition" : "param1==1", 20 | "name" : "c3" 21 | } 22 | ], 23 | "setup": 24 | [ 25 | { 26 | "address" : "0x0401", 27 | "id" : "param1", 28 | "title" : "p1", 29 | "value" : 1 30 | }, 31 | { 32 | "address" : "0x0403", 33 | "condition" : "param1==1", 34 | "id" : "param3", 35 | "title" : "p3", 36 | "value" : 3 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_res11.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "merge condition", 3 | "id": "merge-condition_2", 4 | "name": "merge condition 2", 5 | "slave_id": 2, 6 | "channels": 7 | [ 8 | { 9 | "address": "0x0501", 10 | "name": "c1" 11 | }, 12 | { 13 | "address": "0x0504", 14 | "condition": "param2==3", 15 | "name": "c4" 16 | }, 17 | { 18 | "address": "0x0505", 19 | "condition": "param1==2&¶m2==3", 20 | "name": "c5" 21 | } 22 | ], 23 | "setup": 24 | [ 25 | { 26 | "address" : "0x0401", 27 | "id" : "param1", 28 | "title" : "p1", 29 | "value" : 2 30 | }, 31 | { 32 | "address" : "0x0402", 33 | "id" : "param2", 34 | "title" : "p2", 35 | "value" : 3 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_res12.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type" : "merge condition", 3 | "id" : "merge-condition_2", 4 | "name" : "merge condition 2", 5 | "slave_id" : 2, 6 | "channels" : 7 | [ 8 | { 9 | "address" : "0x0501", 10 | "name" : "c1" 11 | } 12 | ], 13 | "setup" : 14 | [ 15 | { 16 | "address" : "0x0401", 17 | "id" : "param1", 18 | "title" : "p1", 19 | "value" : 2 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_res13.json: -------------------------------------------------------------------------------- 1 | { 2 | "channels" : 3 | [ 4 | { 5 | "address" : "0x0504", 6 | "format" : "s32", 7 | "name" : "Temperature", 8 | "reg_type" : "input" 9 | } 10 | ], 11 | "device_type" : "with conditions", 12 | "id" : "with conditions_2", 13 | "name" : "with conditions 2", 14 | "setup" : 15 | [ 16 | { 17 | "address" : 10, 18 | "id" : "param1", 19 | "required" : true, 20 | "title" : "p1", 21 | "value" : 1 22 | }, 23 | { 24 | "address" : 10, 25 | "condition" : "param1==1", 26 | "id" : "param2", 27 | "required" : true, 28 | "title" : "p2", 29 | "value" : 2 30 | } 31 | ], 32 | "slave_id" : 2 33 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_res2.json: -------------------------------------------------------------------------------- 1 | { 2 | "channels" : 3 | [ 4 | { 5 | "address" : "0x0500", 6 | "format" : "s32", 7 | "name" : "Voltage", 8 | "reg_type" : "input" 9 | }, 10 | { 11 | "address" : "0x0504", 12 | "format" : "s32", 13 | "name" : "Temperature", 14 | "reg_type" : "input" 15 | } 16 | ], 17 | "device_type" : "merge simple with setup", 18 | "id" : "merge-simple-with-setup_2", 19 | "name" : "merge simple with setup 2", 20 | "setup" : 21 | [ 22 | { 23 | "address" : 10000, 24 | "title" : "IODIR", 25 | "value" : "0xffff" 26 | }, 27 | { 28 | "address" : 9999, 29 | "title" : "CONFIG-FLAG", 30 | "value" : 1 31 | } 32 | ], 33 | "slave_id" : 2 34 | } 35 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_res3.json: -------------------------------------------------------------------------------- 1 | { 2 | "channels" : 3 | [ 4 | { 5 | "address" : "0x0500", 6 | "format" : "s32", 7 | "name" : "Voltage", 8 | "reg_type" : "input" 9 | }, 10 | { 11 | "address" : "0x0504", 12 | "format" : "s32", 13 | "name" : "Temperature", 14 | "reg_type" : "input" 15 | }, 16 | { 17 | "address" : "0x0506", 18 | "format" : "s32", 19 | "name" : "New channel", 20 | "reg_type" : "input" 21 | } 22 | ], 23 | "device_type" : "merge simple with setup", 24 | "id" : "1", 25 | "name" : "2", 26 | "setup" : 27 | [ 28 | { 29 | "address" : 50000, 30 | "title" : "new setup", 31 | "value" : "0xffff" 32 | }, 33 | { 34 | "address" : 10000, 35 | "title" : "IODIR", 36 | "value" : "0xffff" 37 | }, 38 | { 39 | "address" : 9999, 40 | "title" : "CONFIG-FLAG", 41 | "value" : 1 42 | } 43 | ], 44 | "slave_id" : 2 45 | } 46 | -------------------------------------------------------------------------------- /test/parser_test/merge_template_res8.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "merge condition", 3 | "id": "merge-condition_2", 4 | "name": "merge condition 2", 5 | "slave_id": 2, 6 | "channels": 7 | [ 8 | { 9 | "address": "0x0501", 10 | "name": "c1" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /test/parser_test/merge_template_res9.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "merge condition", 3 | "id": "merge-condition_2", 4 | "name": "merge condition 2", 5 | "slave_id": 2, 6 | "channels": 7 | [ 8 | { 9 | "address": "0x0501", 10 | "name": "c1" 11 | }, 12 | { 13 | "address" : "0x0502", 14 | "condition" : "param1==1", 15 | "name" : "c2" 16 | }, 17 | { 18 | "address" : "0x0503", 19 | "condition" : "param1==1", 20 | "name" : "c3" 21 | } 22 | ], 23 | "setup": 24 | [ 25 | { 26 | "address" : "0x0401", 27 | "id" : "param1", 28 | "title" : "p1", 29 | "value" : 1 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /test/parser_test/templates/merge-simple-with-setup.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "merge simple with setup", 3 | "device": { 4 | "name": "merge simple with setup", 5 | "id": "merge-simple-with-setup", 6 | "setup": [ 7 | { 8 | "title": "IODIR", 9 | "address": 10000, 10 | "value": "0xffff" 11 | }, 12 | { 13 | "title": "CONFIG-FLAG", 14 | "address": 9999, 15 | "value": 1 16 | } 17 | ], 18 | "channels": [ 19 | { 20 | "name": "Voltage", 21 | "reg_type": "input", 22 | "format": "s32", 23 | "address": "0x0500" 24 | }, 25 | { 26 | "name": "Temperature", 27 | "reg_type": "input", 28 | "format": "s32", 29 | "address": "0x0504" 30 | } 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/parser_test/templates/merge-simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "merge simple", 3 | "device": { 4 | "name": "merge simple", 5 | "id": "merge-simple", 6 | "channels": [ 7 | { 8 | "name": "Voltage", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0500" 12 | }, 13 | { 14 | "name": "Temperature", 15 | "reg_type": "input", 16 | "format": "s32", 17 | "address": "0x0504" 18 | } 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/parser_test/templates/with-conditions.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "with conditions", 3 | "device": { 4 | "name": "with conditions", 5 | "id": "with conditions", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters" : [ 15 | { 16 | "id": "param1", 17 | "title": "p1", 18 | "address": 10, 19 | "required": true 20 | }, 21 | { 22 | "id": "param2", 23 | "title": "p2", 24 | "address": 10, 25 | "required": true, 26 | "condition": "param1==1" 27 | }, 28 | { 29 | "id": "param3", 30 | "title": "p3", 31 | "address": 11, 32 | "enum": [11, 12], 33 | "condition": "param1==2" 34 | } 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/parser_test/templates/with-duplicate-params.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_type": "with duplicate params", 3 | "device": { 4 | "name": "with duplicate params", 5 | "id": "with duplicate params", 6 | "channels": [ 7 | { 8 | "name": "Temperature", 9 | "reg_type": "input", 10 | "format": "s32", 11 | "address": "0x0504" 12 | } 13 | ], 14 | "parameters" : [ 15 | { 16 | "id": "param1", 17 | "title": "p1", 18 | "address": 10, 19 | "required": true 20 | }, 21 | { 22 | "id": "param4", 23 | "title": "p4", 24 | "address": 4 25 | }, 26 | { 27 | "id": "param4", 28 | "title": "p4", 29 | "address": 4, 30 | "condition": "param1==4" 31 | } 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/protocols/fake.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "allOf": [ 5 | { "$ref": "#/definitions/deviceProperties" }, 6 | { "$ref": "#/definitions/common_channels" }, 7 | { "$ref": "#/definitions/common_setup" }, 8 | { "$ref": "#/definitions/slave_id" } 9 | ], 10 | "properties": { 11 | "protocol": { 12 | "type": "string", 13 | "enum": ["fake"] 14 | } 15 | }, 16 | "required": ["protocol", "slave_id"] 17 | } 18 | -------------------------------------------------------------------------------- /test/s2k_expectations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "expector.h" 3 | 4 | class TS2KDeviceExpectations: public virtual TExpectorProvider 5 | { 6 | protected: 7 | void EnqueueSetRelayOffResponse(); 8 | void EnqueueSetRelayOnResponse(); 9 | void EnqueueSetRelay2On(); 10 | void EnqueueSetRelay3On2(); 11 | void EnqueueReadConfig1(); 12 | void EnqueueReadConfig2(); 13 | void EnqueueReadConfig3(); 14 | void EnqueueReadConfig4(); 15 | void EnqueueReadConfig5(); 16 | void EnqueueReadConfig6(); 17 | void EnqueueReadConfig7(); 18 | void EnqueueReadConfig8(); 19 | }; 20 | -------------------------------------------------------------------------------- /test/tcp_port_test.cpp: -------------------------------------------------------------------------------- 1 | #include "port/tcp_port.h" 2 | #include 3 | 4 | using namespace WBMQTT::Testing; 5 | 6 | class TTcpPortTest: public TLoggedFixture 7 | {}; 8 | 9 | TEST_F(TTcpPortTest, TestGetSendTimeBytes) 10 | { 11 | TTcpPortSettings settings; 12 | TTcpPort port(settings); 13 | EXPECT_EQ(port.GetSendTimeBytes(0), std::chrono::microseconds(0)); 14 | EXPECT_EQ(port.GetSendTimeBytes(1), std::chrono::microseconds(1146)); 15 | EXPECT_EQ(port.GetSendTimeBytes(10), std::chrono::microseconds(11459)); 16 | } 17 | 18 | TEST_F(TTcpPortTest, TestGetSendTimeBits) 19 | { 20 | TTcpPortSettings settings; 21 | TTcpPort port(settings); 22 | EXPECT_EQ(port.GetSendTimeBits(0), std::chrono::microseconds(0)); 23 | EXPECT_EQ(port.GetSendTimeBits(1), std::chrono::microseconds(105)); 24 | EXPECT_EQ(port.GetSendTimeBits(10), std::chrono::microseconds(1042)); 25 | } 26 | -------------------------------------------------------------------------------- /test/test_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "test_utils.h" 2 | #include "serial_config.h" 3 | #include 4 | 5 | using namespace WBMQTT; 6 | using namespace WBMQTT::Testing; 7 | 8 | Json::Value GetCommonDeviceSchema() 9 | { 10 | std::string commonSchema = TLoggedFixture::GetDataFilePath("../wb-mqtt-serial-confed-common.schema.json"); 11 | return WBMQTT::JSON::Parse(commonSchema); 12 | } 13 | 14 | Json::Value GetTemplatesSchema() 15 | { 16 | std::string templateSchema = TLoggedFixture::GetDataFilePath("../wb-mqtt-serial-device-template.schema.json"); 17 | return LoadConfigTemplatesSchema(templateSchema, GetCommonDeviceSchema()); 18 | } -------------------------------------------------------------------------------- /test/test_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "json_common.h" 4 | #include "serial_exc.h" 5 | #include 6 | 7 | template void CheckExceptionMsg(FnType fn, const std::string& msg) 8 | { 9 | try { 10 | fn(); 11 | } catch (const TSerialDeviceTransientErrorException& e) { 12 | ASSERT_EQ(e.what(), "Serial protocol error: " + msg); 13 | throw; 14 | } catch (const std::exception& e) { 15 | ASSERT_EQ(e.what(), msg); 16 | throw; 17 | } 18 | } 19 | 20 | Json::Value GetCommonDeviceSchema(); 21 | Json::Value GetTemplatesSchema(); 22 | -------------------------------------------------------------------------------- /test/translation-templates/templates1/config-translations.json: -------------------------------------------------------------------------------- 1 | //no translations 2 | { 3 | "device_type": "with translations", 4 | "title": "with translations", 5 | "device": { 6 | "name": "with translations", 7 | "id": "with translations", 8 | "channels": [ 9 | { 10 | "name": "English temperature", 11 | "reg_type": "input", 12 | "format": "s32", 13 | "address": "0x0504" 14 | } 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/translation-templates/tr1.json: -------------------------------------------------------------------------------- 1 | { 2 | "en": { 3 | "": "English temperature", 4 | "": "with translations" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/translation-templates/tr2.json: -------------------------------------------------------------------------------- 1 | { 2 | "en": { 3 | "": "p22", 4 | "": "one", 5 | "": "two", 6 | "": "Group 1", 7 | "": "Sub1", 8 | "": "c11", 9 | "": "English temperature tr", 10 | "": "English title translation", 11 | "": "Description" 12 | }, 13 | "ru": { 14 | "": "Температура", 15 | "": "Перевод", 16 | "": "Параметр", 17 | "": "Один", 18 | "": "Группа 1", 19 | "": "Часть 1", 20 | "": "Описание", 21 | "": "Группа 1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/uniel_expectations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "expector.h" 3 | 4 | class TUnielDeviceExpectations: public virtual TExpectorProvider 5 | { 6 | protected: 7 | void EnqueueVoltageQueryResponse(); 8 | void EnqueueRelayOffQueryResponse(); 9 | void EnqueueRelayOnQueryResponse(); 10 | void EnqueueThreshold0QueryResponse(); 11 | void EnqueueBrightnessQueryResponse(); 12 | void EnqueueSetRelayOnResponse(); 13 | void EnqueueSetRelayOffResponse(); 14 | void EnqueueSetLowThreshold0Response(); 15 | void EnqueueSetBrightnessResponse(); 16 | }; 17 | -------------------------------------------------------------------------------- /wb-mqtt-serial-dummy.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "title": "Serial Device Driver Configuration", 5 | 6 | "configFile": { 7 | "path": "/etc/wb-mqtt-serial.conf", 8 | "service": "wb-mqtt-serial", 9 | "fromJSON": ["wb-mqtt-serial", "-J"], 10 | "validate": false, 11 | "editor": "serial-config" 12 | }, 13 | 14 | "translations": { 15 | "ru": { 16 | "Serial Device Driver Configuration": "Настройка драйвера Serial-устройств" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /wb-mqtt-serial.wbconfigs: -------------------------------------------------------------------------------- 1 | wb_move /etc/wb-mqtt-serial.conf 2 | wb_move /etc/wb-mqtt-serial.conf.d --------------------------------------------------------------------------------