Merge pull request #1591 from fengzeroz/main

modbus pytest case
This commit is contained in:
fengzeroz
2023-10-12 15:25:54 +08:00
committed by GitHub
17 changed files with 845 additions and 562 deletions
+2 -2
View File
@@ -8,8 +8,8 @@ on:
- published
env:
VERSION: 2.6.0
UI_VERSION: 2.6.0
VERSION: 2.7.0
UI_VERSION: 2.6.1
BRANCH: main
jobs:
-197
View File
@@ -1,197 +0,0 @@
*** Settings ***
Resource resource/api.resource
Resource resource/common.resource
Resource resource/error.resource
Resource resource/driver.resource
Suite Setup Modbus Test Setup
Suite Teardown Modbus Test Teardown
*** Variables ***
${modbus_rtu_node} modbus_rtu_node
${PLUGIN-MODBUS-RTU} Modbus RTU
${MODBUS_RTU_CONFIG} {"link": 1, "timeout": 3000, "interval": 10, "device": "", "stop": 0, "parity": 0, "baud": 4,"data": 3, "host": "127.0.0.1", "port": 60503, "connection_mode": 0, "transport_mode": 0}
${MODBUS_RTU_CONFIG_WRANING} {"link": 1, "host": "127.0.0.1","port": 60503,"connection_mode": 0}
${hold_bit} {"name": "hold_bit", "address": "1!400001.15", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${hold_int16} {"name": "hold_int16", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_uint16} {"name": "hold_uint16", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT16}}
${hold_int32} {"name": "hold_int32", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}}
${hold_uint32} {"name": "hold_uint32", "address": "1!400015", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT32}}
${hold_float} {"name": "hold_float", "address": "1!400017", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_FLOAT}}
${hold_string} {"name": "hold_string", "address": "1!400020.10", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
${coil_bit_1} {"name": "coil_bit_1", "address": "1!000001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_2} {"name": "coil_bit_2", "address": "1!000002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_3} {"name": "coil_bit_3", "address": "1!000003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_4} {"name": "coil_bit_4", "address": "1!000005", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_5} {"name": "coil_bit_5", "address": "1!000010", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${input_bit_1} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_2} {"name": "input_bit_2", "address": "1!100002", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_3} {"name": "input_bit_3", "address": "1!100003", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_4} {"name": "input_bit_4", "address": "1!100005", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_5} {"name": "input_bit_5", "address": "1!100010", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_register_bit} {"name": "input_register_bit", "address": "1!30101.15", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_register_int16} {"name": "input_register_int16", "address": "1!30101", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
${input_register_uint16} {"name": "input_register_uint16", "address": "1!30102", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_UINT16}}
${input_register_int32} {"name": "input_register_int32", "address": "1!30103", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT32}}
${input_register_uint32} {"name": "input_register_uint32", "address": "1!30115", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_UINT32}}
${input_register_float} {"name": "input_register_float", "address": "1!30117", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_FLOAT}}
${input_register_string} {"name": "input_register_string", "address": "1!30120.10", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_STRING}}
${hold_int16_address_update} {"name": "hold_int16", "address": "1!400100", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_int16_type_update} {"name": "hold_int16", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}}
${input_bit_1_name_wrong} {"name": "input_bit", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_1_attribute_unmatch} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${input_bit_1_type_unmatch} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
${hold_int16_1} {"name": "hold_int16_1", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_int16_2} {"name": "hold_int16_2", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_int16_3} {"name": "hold_int16_3", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_string_tags_1} {"name": "hold_string_tags_1", "address": "1!40001.4", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
${hold_string_tags_2} {"name": "hold_string_tags_2", "address": "1!40003.4", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
${hold_string_tags_3} {"name": "hold_string_tags_3", "address": "1!40005.4", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
*** Test Cases ***
Set a node with right settings, it should be success.
[Template] Set a ${node} with right ${node_settings}, it will be success.
${modbus_rtu_node} ${MODBUS_RTU_CONFIG}
Set a node with wrong settings, it should be failure.
[Template] Set a ${node} with wrong ${node_settings}, it will be failure.
${modbus_rtu_node} ${MODBUS_RTU_CONFIG_WRANING}
Set tags with multiple address and types and attribute, it should be success.
[Template] Add a ${tag} with right address and type and attribute from ${node}, it will be success.
${hold_int16} ${modbus_rtu_node}
${hold_uint16} ${modbus_rtu_node}
${hold_int32} ${modbus_rtu_node}
${hold_uint32} ${modbus_rtu_node}
${hold_float} ${modbus_rtu_node}
${hold_string} ${modbus_rtu_node}
${coil_bit_1} ${modbus_rtu_node}
${coil_bit_2} ${modbus_rtu_node}
${coil_bit_3} ${modbus_rtu_node}
${coil_bit_4} ${modbus_rtu_node}
${coil_bit_5} ${modbus_rtu_node}
${input_register_int16} ${modbus_rtu_node}
${input_register_uint16} ${modbus_rtu_node}
${input_register_int32} ${modbus_rtu_node}
${input_register_uint32} ${modbus_rtu_node}
${input_register_float} ${modbus_rtu_node}
${input_register_string} ${modbus_rtu_node}
${input_bit_1} ${modbus_rtu_node}
${input_bit_2} ${modbus_rtu_node}
${input_bit_3} ${modbus_rtu_node}
${input_bit_4} ${modbus_rtu_node}
${input_bit_5} ${modbus_rtu_node}
Set tags with unmatch address, type or attribute, it should be failure.
[Template] Set a ${tag} with unmatch address, type or attribute from ${node}, it will be failure and return ${resp_status} and ${error_code}.
${input_bit_1_type_unmatch} ${modbus_rtu_node} 200 ${NEU_ERR_TAG_TYPE_NOT_SUPPORT}
${input_bit_1_attribute_unmatch} ${modbus_rtu_node} 200 ${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT}
Write and Read all type tag with same slave id in hold register and coil, it should be success.
[Template] Write and Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${hold_int16} hold_int16 ${modbus_rtu_node} Compare Tag Value As Int 120
${hold_uint16} hold_uint16 ${modbus_rtu_node} Compare Tag Value As Int 65535
${hold_int32} hold_int32 ${modbus_rtu_node} Compare Tag Value As Int 77889912
${hold_uint32} hold_uint32 ${modbus_rtu_node} Compare Tag Value As Int 88991232
${hold_float} hold_float ${modbus_rtu_node} Compare Tag Value As Float 12.34
${hold_string} hold_string ${modbus_rtu_node} Compare Tag Value As Strings "abc123"
${coil_bit_1} coil_bit_1 ${modbus_rtu_node} Compare Tag Value As Int 1
${coil_bit_2} coil_bit_2 ${modbus_rtu_node} Compare Tag Value As Int 0
${coil_bit_3} coil_bit_3 ${modbus_rtu_node} Compare Tag Value As Int 0
${coil_bit_4} coil_bit_4 ${modbus_rtu_node} Compare Tag Value As Int 1
${coil_bit_5} coil_bit_5 ${modbus_rtu_node} Compare Tag Value As Int 1
Read all type tag with same slave id in input register and input, it should be success.
[Template] Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${input_register_int16} input_register_int16 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_register_uint16} input_register_uint16 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_register_int32} input_register_int32 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_register_uint32} input_register_uint32 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_register_float} input_register_float ${modbus_rtu_node} Compare Tag Value As Float 0
${input_register_string} input_register_string ${modbus_rtu_node} Compare Tag Value As Strings ""
${input_bit_1} input_bit_1 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_bit_2} input_bit_2 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_bit_3} input_bit_3 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_bit_4} input_bit_4 ${modbus_rtu_node} Compare Tag Value As Int 0
${input_bit_5} input_bit_5 ${modbus_rtu_node} Compare Tag Value As Int 0
Read some tags at time, it will be success.
[Template] Read some ${tags} from ${node}, it will be success.
${input_register_int16},${input_register_uint16},${input_register_int32},${input_register_uint32},${input_register_float},${input_register_string},${input_register_bit} ${modbus_rtu_node}
${hold_int16},${hold_uint16},${hold_int32},${hold_uint32},${hold_float},${hold_string},${hold_bit} ${modbus_rtu_node}
${coil_bit_1},${coil_bit_2},${coil_bit_3},${coil_bit_4},${coil_bit_5} ${modbus_rtu_node}
${input_bit_1},${input_bit_2},${input_bit_3},${input_bit_4},${input_bit_5} ${modbus_rtu_node}
Write and read a tag with same name and same address that in different groups, it should be success.
${groups}= Create List group-1 group-2 group-3
Write and read a ${hold_int16} with same hold_int16 and same address in different ${groups} that from ${modbus_rtu_node}, using Compare Tag Value As Int to check the 2, it will be success.
Write and read a tag with same name but different address that in different groups, it should be success.
${groups}= Create List group-1 group-2 group-3
Write and read ${hold_int16} ${hold_int16_address_update} with same hold_int16 but different address in different ${groups} that from ${modbus_rtu_node}, using Compare Tag Value As Int to check the 2, it will be success.
Update a tag with right address and types and attribute, it will be success
[Template] Update a ${tag} by a ${tag_update} named ${tag_name} from ${node} , it can read and write, using ${check} to check the ${value}, it will be success.
${hold_int16} ${hold_int16_address_update} hold_int16 ${modbus_rtu_node} Compare Tag Value As Int 120
${hold_int16} ${hold_int16_type_update} hold_int16 ${modbus_rtu_node} Compare Tag Value As Int 120
Update a tag with unmatch address and types and attribute, it should be failure.
[Template] Update a ${tag} by a ${tag_update} with the unmatch settings from ${node} , it will be failure and return ${resp_status} and ${error_code}.
${input_bit_1} ${input_bit_1_attribute_unmatch} ${modbus_rtu_node} 200 ${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT}
${input_bit_1} ${input_bit_1_type_unmatch} ${modbus_rtu_node} 200 ${NEU_ERR_TAG_TYPE_NOT_SUPPORT}
${input_bit_1} ${input_bit_1_name_wrong} ${modbus_rtu_node} 200 ${NEU_ERR_TAG_NOT_EXIST}
Write 3 tags 1 time, it should return success
[Template] Write and Read ${tag_data1}, ${tag_data2} and ${tag_data3} named ${tag1}, ${tag2} and ${tag3} from ${node}, using ${check} to check the ${value1}, ${value2} and ${value3}, it will be success.
${hold_int16_1} ${hold_int16_2} ${hold_int16_3} hold_int16_1 hold_int16_2 hold_int16_3 ${modbus_rtu_node} Compare Tag Value As Int 1 2 3
${coil_bit_1} ${coil_bit_2} ${coil_bit_3} coil_bit_1 coil_bit_2 coil_bit_3 ${modbus_rtu_node} Compare Tag Value As Int 1 0 1
${hold_string_tags_1} ${hold_string_tags_2} ${hold_string_tags_3} hold_string_tags_1 hold_string_tags_2 hold_string_tags_3 ${modbus_rtu_node} Compare Tag Value As Strings "a" "b" "c"
Write a value to a tag that don't exit in plc or neuron, it will be failure.
[Template] Write a ${value} to a ${tag} with named ${tag_name} that don't exist in neuron or plc from ${node}, it will be failure.
12 ${input_bit_1} input ${modbus_rtu_node}
Write value to a tag without write attribute, it will be failure.
[Template] Write a ${value} to a ${tag} named ${tag_name} that without write attribute from ${node}, it will be failure.
1 ${input_bit_1} input_bit_1 ${modbus_rtu_node}
Write and read a value to a tag when the node is stoped, it will be failure.
[Template] Write and read a ${value} to a ${tag} named ${tag_name} when the ${node} is stoped, it will be failure.
1 ${hold_int16} hold_int16 ${modbus_rtu_node}
*** Keywords ***
Modbus Test Setup
Start Modbus-RTU Simulator
Start Neuronx
${res}= Add Node ${modbus_rtu_node} ${PLUGIN-MODBUS-RTU}
Check Response Status ${res} 200
${res}= Node Setting ${modbus_rtu_node} ${MODBUS_RTU_CONFIG}
Check Response Status ${res} 200
${state}= Get Node State ${modbus_rtu_node}
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
Modbus Test Teardown
Del Node ${modbus_rtu_node}
Stop Neuronx
Terminate All Processes kill=false
Start Modbus-RTU Simulator
${handle} = Start Process ${MODBUS_TCP_SERVER_SIMULATOR} rtu 60503 ip_v4 cwd=build/simulator
[Return] ${handle}
-248
View File
@@ -1,248 +0,0 @@
*** Settings ***
Library Process
Library OperatingSystem
Resource resource/api.resource
Resource resource/common.resource
Resource resource/error.resource
Resource resource/driver.resource
Suite Setup Modbus Test Setup
Suite Teardown Modbus Test Teardown
*** Variables ***
${PLUGIN-MODBUS-TCP} Modbus TCP
${modbus_tcp_node} modbus_tcp_node
${MODBUS_TCP_CONFIG} {"connection_mode": 0, "transport_mode": 0, "interval": 0, "host": "127.0.0.1","port": 60502,"timeout": 3000}
${MODBUS_TCP_CONFIG_WRONG} {"connection_mode": 0,"host": "127.0.0.1", "port": 60502}
${hold_bit} {"name": "hold_bit", "address": "1!400001.15", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${hold_int16} {"name": "hold_int16", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_uint16} {"name": "hold_uint16", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT16}}
${hold_int32} {"name": "hold_int32", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}}
${hold_uint32} {"name": "hold_uint32", "address": "1!400015", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT32}}
${hold_float} {"name": "hold_float", "address": "1!400017", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_FLOAT}}
${hold_string} {"name": "hold_string", "address": "1!400020.10", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
${hold_int16_s} {"name": "hold_int16_s", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_INT16}, "value": 1}
${hold_uint16_s} {"name": "hold_uint16_s", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_UINT16}, "value": 1}
${hold_int32_s} {"name": "hold_int32_s", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_INT32}, "value": 1}
${hold_uint32_s} {"name": "hold_uint32_s", "address": "1!400015", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_UINT32}, "value": 1}
${hold_float_s} {"name": "hold_float_s", "address": "1!400017", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_FLOAT}, "value": 1.0}
${hold_string_s} {"name": "hold_string_s", "address": "1!400020.10", "attribute": ${TAG_ATTRIBUTE_STATIC_RW}, "type": ${TAG_TYPE_STRING}, "value": "a"}
${coil_bit_1} {"name": "coil_bit_1", "address": "1!000001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_2} {"name": "coil_bit_2", "address": "1!000002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_3} {"name": "coil_bit_3", "address": "1!000003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_4} {"name": "coil_bit_4", "address": "1!000005", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${coil_bit_5} {"name": "coil_bit_5", "address": "1!000010", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${input_bit_1} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_2} {"name": "input_bit_2", "address": "1!100002", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_3} {"name": "input_bit_3", "address": "1!100003", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_4} {"name": "input_bit_4", "address": "1!100005", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_5} {"name": "input_bit_5", "address": "1!100010", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_register_bit} {"name": "input_register_bit", "address": "1!30101.15", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_register_int16} {"name": "input_register_int16", "address": "1!30101", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
${input_register_uint16} {"name": "input_register_uint16", "address": "1!30102", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_UINT16}}
${input_register_int32} {"name": "input_register_int32", "address": "1!30103", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT32}}
${input_register_uint32} {"name": "input_register_uint32", "address": "1!30115", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_UINT32}}
${input_register_float} {"name": "input_register_float", "address": "1!30117", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_FLOAT}}
${input_register_string} {"name": "input_register_string", "address": "1!30120.10", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_STRING}}
${hold_int16_address_update} {"name": "hold_int16", "address": "1!400100", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_int16_type_update} {"name": "hold_int16", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}}
${input_bit_1_name_wrong} {"name": "input_bit", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_BIT}}
${input_bit_1_attribute_unmatch} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_BIT}}
${input_bit_1_type_unmatch} {"name": "input_bit_1", "address": "1!100001", "attribute": ${TAG_ATTRIBUTE_READ}, "type": ${TAG_TYPE_INT16}}
${hold_int16_decimal} {"name": "hold_int16_decimal", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}, "decimal": 0.1}
${hold_uint16_decimal} {"name": "hold_uint16_decimal", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT16}, "decimal": 0.1}
${hold_int32_decimal} {"name": "hold_int32_decimal", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT32}, "decimal": 0.1}
${hold_uint32_decimal} {"name": "hold_uint32_decimal", "address": "1!400015", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_UINT32}, "decimal": 0.1}
${hold_float_decimal} {"name": "hold_float_decimal", "address": "1!400017", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_FLOAT}, "decimal": 0.1}
${hold_double_decimal} {"name": "hold_double_decimal", "address": "1!400027", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_DOUBLE}, "decimal": 0.1}
${hold_float_precision} {"name": "hold_float_precision", "address": "1!400030", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_FLOAT}, "precision": 2}
${hold_double_precision} {"name": "hold_double_precision", "address": "1!400040", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_DOUBLE}, "precision": 2}
${hold_int16_1} {"name": "hold_int16_1", "address": "1!400001", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_int16_2} {"name": "hold_int16_2", "address": "1!400002", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_int16_3} {"name": "hold_int16_3", "address": "1!400003", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_INT16}}
${hold_string_tags_1} {"name": "hold_string_tags_1", "address": "1!40001.4", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
${hold_string_tags_2} {"name": "hold_string_tags_2", "address": "1!40003.4", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
${hold_string_tags_3} {"name": "hold_string_tags_3", "address": "1!40005.4", "attribute": ${TAG_ATTRIBUTE_RW}, "type": ${TAG_TYPE_STRING}}
*** Test Cases ***
Set a node with right settings, it should be success.
[Template] Set a ${node} with right ${node_settings}, it will be success.
${modbus_tcp_node} ${MODBUS_TCP_CONFIG}
Set a node with wrong settings, it should be failure.
[Template] Set a ${node} with wrong ${node_settings}, it will be failure.
${modbus_tcp_node} ${MODBUS_TCP_CONFIG_WRONG}
Set tags with multiple address and types and attribute, it should be success.
[Template] Add a ${tag} with right address and type and attribute from ${node}, it will be success.
${hold_int16} ${modbus_tcp_node}
${hold_uint16} ${modbus_tcp_node}
${hold_int32} ${modbus_tcp_node}
${hold_uint32} ${modbus_tcp_node}
${hold_float} ${modbus_tcp_node}
${hold_string} ${modbus_tcp_node}
${hold_int16_s} ${modbus_tcp_node}
${hold_uint16_s} ${modbus_tcp_node}
${hold_int32_s} ${modbus_tcp_node}
${hold_uint32_s} ${modbus_tcp_node}
${hold_float_s} ${modbus_tcp_node}
${hold_string_s} ${modbus_tcp_node}
${coil_bit_1} ${modbus_tcp_node}
${coil_bit_2} ${modbus_tcp_node}
${coil_bit_3} ${modbus_tcp_node}
${coil_bit_4} ${modbus_tcp_node}
${coil_bit_5} ${modbus_tcp_node}
${input_register_int16} ${modbus_tcp_node}
${input_register_uint16} ${modbus_tcp_node}
${input_register_int32} ${modbus_tcp_node}
${input_register_uint32} ${modbus_tcp_node}
${input_register_float} ${modbus_tcp_node}
${input_register_string} ${modbus_tcp_node}
${input_bit_1} ${modbus_tcp_node}
${input_bit_2} ${modbus_tcp_node}
${input_bit_3} ${modbus_tcp_node}
${input_bit_4} ${modbus_tcp_node}
${input_bit_5} ${modbus_tcp_node}
Set tags with unmatch address, type or attribute, it should be failure.
[Template] Set a ${tag} with unmatch address, type or attribute from ${node}, it will be failure and return ${resp_status} and ${error_code}.
${input_bit_1_type_unmatch} ${modbus_tcp_node} 200 ${NEU_ERR_TAG_TYPE_NOT_SUPPORT}
${input_bit_1_attribute_unmatch} ${modbus_tcp_node} 200 ${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT}
Write and Read all type tag with same slave id in hold register and coil, it should be success.
[Template] Write and Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${hold_int16} hold_int16 ${modbus_tcp_node} Compare Tag Value As Int 120
${hold_uint16} hold_uint16 ${modbus_tcp_node} Compare Tag Value As Int 65535
${hold_int32} hold_int32 ${modbus_tcp_node} Compare Tag Value As Int 77889912
${hold_uint32} hold_uint32 ${modbus_tcp_node} Compare Tag Value As Int 88991232
${hold_float} hold_float ${modbus_tcp_node} Compare Tag Value As Float 12.34
${hold_string} hold_string ${modbus_tcp_node} Compare Tag Value As Strings "abc123"
${coil_bit_1} coil_bit_1 ${modbus_tcp_node} Compare Tag Value As Int 1
${coil_bit_2} coil_bit_2 ${modbus_tcp_node} Compare Tag Value As Int 0
${coil_bit_3} coil_bit_3 ${modbus_tcp_node} Compare Tag Value As Int 0
${coil_bit_4} coil_bit_4 ${modbus_tcp_node} Compare Tag Value As Int 1
${coil_bit_5} coil_bit_5 ${modbus_tcp_node} Compare Tag Value As Int 1
Read all type tag with same slave id in input register and input, it should be success.
[Template] Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${input_register_int16} input_register_int16 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_register_uint16} input_register_uint16 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_register_int32} input_register_int32 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_register_uint32} input_register_uint32 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_register_float} input_register_float ${modbus_tcp_node} Compare Tag Value As Float 0
${input_register_string} input_register_string ${modbus_tcp_node} Compare Tag Value As Strings ""
${input_bit_1} input_bit_1 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_bit_2} input_bit_2 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_bit_3} input_bit_3 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_bit_4} input_bit_4 ${modbus_tcp_node} Compare Tag Value As Int 0
${input_bit_5} input_bit_5 ${modbus_tcp_node} Compare Tag Value As Int 0
Read some tags at time, it will be success.
[Template] Read some ${tags} from ${node}, it will be success.
${input_register_int16},${input_register_uint16},${input_register_int32},${input_register_uint32},${input_register_float},${input_register_string},${input_register_bit} ${modbus_tcp_node}
${hold_int16},${hold_uint16},${hold_int32},${hold_uint32},${hold_float},${hold_string},${hold_bit} ${modbus_tcp_node}
${coil_bit_1},${coil_bit_2},${coil_bit_3},${coil_bit_4},${coil_bit_5} ${modbus_tcp_node}
${input_bit_1},${input_bit_2},${input_bit_3},${input_bit_4},${input_bit_5} ${modbus_tcp_node}
Write and read a tag with same name and same address that in different groups, it should be success.
${groups}= Create List group-1 group-2 group-3
Write and read a ${hold_int16} with same hold_int16 and same address in different ${groups} that from ${modbus_tcp_node}, using Compare Tag Value As Int to check the 2, it will be success.
Write and read a tag with same name but different address that in different groups, it should be success.
${groups}= Create List group-1 group-2 group-3
Write and read ${hold_int16} ${hold_int16_address_update} with same hold_int16 but different address in different ${groups} that from ${modbus_tcp_node}, using Compare Tag Value As Int to check the 2, it will be success.
Update a tag with right address and types and attribute, it will be success
[Template] Update a ${tag} by a ${tag_update} named ${tag_name} from ${node} , it can read and write, using ${check} to check the ${value}, it will be success.
${hold_int16} ${hold_int16_address_update} hold_int16 ${modbus_tcp_node} Compare Tag Value As Int 120
${hold_int16} ${hold_int16_type_update} hold_int16 ${modbus_tcp_node} Compare Tag Value As Int 120
Write 3 tags 1 time, it should return success
[Template] Write and Read ${tag_data1}, ${tag_data2} and ${tag_data3} named ${tag1}, ${tag2} and ${tag3} from ${node}, using ${check} to check the ${value1}, ${value2} and ${value3}, it will be success.
${hold_int16_1} ${hold_int16_2} ${hold_int16_3} hold_int16_1 hold_int16_2 hold_int16_3 ${modbus_tcp_node} Compare Tag Value As Int 1 2 3
${coil_bit_1} ${coil_bit_2} ${coil_bit_3} coil_bit_1 coil_bit_2 coil_bit_3 ${modbus_tcp_node} Compare Tag Value As Int 1 0 1
${hold_string_tags_1} ${hold_string_tags_2} ${hold_string_tags_3} hold_string_tags_1 hold_string_tags_2 hold_string_tags_3 ${modbus_tcp_node} Compare Tag Value As Strings "a" "b" "c"
Add a tag with decimal, it should return success
[Template] Add a ${tag} with right address and type and attribute from ${node}, it will be success.
${hold_int16_decimal} ${modbus_tcp_node}
${hold_uint16_decimal} ${modbus_tcp_node}
${hold_int32_decimal} ${modbus_tcp_node}
${hold_uint32_decimal} ${modbus_tcp_node}
${hold_float_decimal} ${modbus_tcp_node}
${hold_double_decimal} ${modbus_tcp_node}
Write and read a value to a tag with decimal, it should return success
[Template] Write and Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${hold_int16_decimal} hold_int16_decimal ${modbus_tcp_node} Compare Tag Value As Int 120
${hold_uint16_decimal} hold_uint16_decimal ${modbus_tcp_node} Compare Tag Value As Int 120
${hold_int32_decimal} hold_int32_decimal ${modbus_tcp_node} Compare Tag Value As Int 120
${hold_uint32_decimal} hold_uint32_decimal ${modbus_tcp_node} Compare Tag Value As Int 120
${hold_float_decimal} hold_float_decimal ${modbus_tcp_node} Compare Tag Value As Float 120.5
${hold_double_decimal} hold_double_decimal ${modbus_tcp_node} Compare Tag Value As Float 120.5
Add a tag with precision, it should return success
[Template] Add a ${tag} with right address and type and attribute from ${node}, it will be success.
${hold_float_precision} ${modbus_tcp_node}
${hold_double_precision} ${modbus_tcp_node}
Write and read a value to a tag with precision, it should return success
[Template] Write and Read a ${tag} named ${tag_name} from ${node}, using ${check} to check the ${value}, it will be success.
${hold_float_precision} hold_float_precision ${modbus_tcp_node} Compare Tag Value As Float 120.5
${hold_double_precision} hold_double_precision ${modbus_tcp_node} Compare Tag Value As Float 1111111111111111111111111111111111111111.1
Update a tag with unmatch address and types and attribute, it should be failure.
[Template] Update a ${tag} by a ${tag_update} with the unmatch settings from ${node} , it will be failure and return ${resp_status} and ${error_code}.
${input_bit_1} ${input_bit_1_attribute_unmatch} ${modbus_tcp_node} 200 ${NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT}
${input_bit_1} ${input_bit_1_type_unmatch} ${modbus_tcp_node} 200 ${NEU_ERR_TAG_TYPE_NOT_SUPPORT}
${input_bit_1} ${input_bit_1_name_wrong} ${modbus_tcp_node} 200 ${NEU_ERR_TAG_NOT_EXIST}
Write a value to a tag that don't exit in plc or neuron, it will be failure.
[Template] Write a ${value} to a ${tag} with named ${tag_name} that don't exist in neuron or plc from ${node}, it will be failure.
12 ${input_bit_1} input ${modbus_tcp_node}
Write value to a tag without write attribute, it will be failure.
[Template] Write a ${value} to a ${tag} named ${tag_name} that without write attribute from ${node}, it will be failure.
1 ${input_bit_1} input_bit_1 ${modbus_tcp_node}
Write and read a value to a tag when the node is stoped, it will be failure.
[Template] Write and read a ${value} to a ${tag} named ${tag_name} when the ${node} is stoped, it will be failure.
1 ${hold_int16} hold_int16 ${modbus_tcp_node}
*** Keywords ***
Modbus Test Setup
Start Modbus Simulator
Start Neuronx
${res}= Add Node ${modbus_tcp_node} ${PLUGIN-MODBUS-TCP}
Check Response Status ${res} 200
${res}= Node Setting ${modbus_tcp_node} ${MODBUS_TCP_CONFIG}
Check Response Status ${res} 200
${state}= Get Node State ${modbus_tcp_node}
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
# Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_CONNECTED}
Modbus Test Teardown
Del Node ${modbus_tcp_node}
Stop Neuronx
Terminate All Processes kill=false
-86
View File
@@ -1,86 +0,0 @@
*** Settings ***
Resource resource/api.resource
Resource resource/common.resource
Resource resource/error.resource
Suite Setup Start Neuronx
Suite Teardown Stop Neuronx
*** Test Cases ***
Start an unconfigured node, it should return failure
${res}= Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Sleep 1s
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_INIT}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
${res} = Node Ctl modbus-node ${NODE_CTL_START}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_NOT_READY}
Stop node that is ready(init/idle), it should return failure
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_NOT_RUNNING}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_INIT}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
[Teardown] Del Node modbus-node
Start the configured node, it should return success
${res}= Add Node modbus-node ${PLUGIN-MODBUS-TCP}
Sleep 1s
Node Setting modbus-node ${MODBUS_TCP_CONFIG}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_STOP}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
Stop node that is stopped, it should return failure
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_IS_STOPED}
Start the stopped node, it should return success
${res} = Node Ctl modbus-node ${NODE_CTL_START}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
Start the running node, it should return failure
${res} = Node Ctl modbus-node ${NODE_CTL_START}
Check Response Status ${res} 409
Check Error Code ${res} ${NEU_ERR_NODE_IS_RUNNING}
When setting up a READY/RUNNING/STOPED node, the node status will not change
${res} = Node Setting modbus-node ${MODBUS_TCP_CONFIG}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_RUNNING}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
${res} = Node Ctl modbus-node ${NODE_CTL_STOP}
Check Response Status ${res} 200
Check Error Code ${res} ${NEU_ERR_SUCCESS}
${res} = Node Setting modbus-node ${MODBUS_TCP_CONFIG}
${state} = Get Node State modbus-node
Should Be Equal As Integers ${state}[running] ${NODE_STATE_STOP}
Should Be Equal As Integers ${state}[link] ${NODE_LINK_STATE_DISCONNECTED}
[Teardown] Del Node modbus-node
+3 -2
View File
@@ -215,13 +215,14 @@ ssize_t modbus_s_tcp_req(uint8_t *req, uint16_t req_len, uint8_t *res,
break;
case MODBUS_WRITE_S_COIL:
case MODBUS_WRITE_M_COIL:
case MODBUS_WRITE_S_HOLD_REG:
case MODBUS_WRITE_S_HOLD_REG:
case MODBUS_WRITE_M_HOLD_REG:
nlog_info(
"write register: slave: %d, function: %d, address: %d, n: %d, "
"nbyte: %d\n",
code->slave_id, code->function, ntohs(address->start_address),
code->function != MODBUS_WRITE_S_HOLD_REG ? ntohs(address->n_reg) : 1,
code->function != MODBUS_WRITE_S_HOLD_REG ? ntohs(address->n_reg)
: 1,
code->function != MODBUS_WRITE_S_HOLD_REG ? data->n_byte : 2);
modbus_write(&tcp_registers[code->slave_id - 1], code->function,
address, data, value);
+3
View File
@@ -0,0 +1,3 @@
import sys
sys.path.append("tests/ft")
+123
View File
@@ -0,0 +1,123 @@
import neuron.api as api
import neuron.error as error
import neuron.config as config
from neuron.common import *
class TestDriver:
@description(given="running neuron", when="add driver node", then="add success")
@pytest.mark.parametrize('node,plugin', [('modbus-tcp-1', config.PLUGIN_MODBUS_TCP),
('modbus-rtu-1', config.PLUGIN_MODBUS_RTU)])
def test_create_node(self, node, plugin):
response = api.add_node(node=node,
plugin=plugin)
assert 200 == response.status_code
assert error.NEU_ERR_SUCCESS == response.json()['error']
@description(given="created node", when="get node state", then="state is init")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_node_init(self, node):
response = api.get_nodes_state(node=node)
assert 200 == response.status_code
assert config.NEU_NODE_STATE_INIT == response.json()['running']
@description(given="created node", when="stop node", then="stop failed")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_init_node_stop(self, node):
response = api.node_ctl(node=node, ctl=config.NEU_CTL_STOP)
assert 409 == response.status_code
@description(given="modbus tcp node", when="setting modbus tcp node", then="setting success")
def test_modbus_tcp_setting(self):
response = api.modbus_tcp_node_setting(node='modbus-tcp-1', port=502)
assert 200 == response.status_code
assert error.NEU_ERR_SUCCESS == response.json()['error']
@description(given="modbus rtu node", when="setting modbus rtu node", then="setting success")
def test_modbus_rtu_setting(self):
response = api.modbus_rtu_node_setting(node='modbus-rtu-1', port=502)
assert 200 == response.status_code
assert error.NEU_ERR_SUCCESS == response.json()['error']
def test_wait_state(self):
time.sleep(4)
@description(given="configured node", when="get node state", then="state is running")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_node_ready(self, node):
response = api.get_nodes_state(node=node)
assert 200 == response.status_code
assert config.NEU_NODE_STATE_RUNNING == response.json()['running']
@description(given="running modbus tcp node", when="setting modbus tcp node", then="state not change")
def test_running_modbus_tcp_setting(self):
response = api.modbus_tcp_node_setting(node='modbus-tcp-1', port=502)
assert 200 == response.status_code
response = api.get_nodes_state(node='modbus-tcp-1')
assert 200 == response.status_code
assert config.NEU_NODE_STATE_RUNNING == response.json()['running']
@description(given="running modbus rtu node", when="setting modbus rtu node", then="state not change")
def test_running_modbus_rtu_setting(self):
response = api.modbus_rtu_node_setting(node='modbus-rtu-1', port=502)
assert 200 == response.status_code
response = api.get_nodes_state(node='modbus-tcp-1')
assert 200 == response.status_code
assert config.NEU_NODE_STATE_RUNNING == response.json()['running']
@description(given="running node", when="stop node", then="state is stopped")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_node_stop(self, node):
response = api.node_ctl(node=node, ctl=config.NEU_CTL_STOP)
assert 200 == response.status_code
response = api.get_nodes_state(node=node)
assert 200 == response.status_code
assert config.NEU_NODE_STATE_STOPPED == response.json()['running']
@description(given="stopped modbus tcp node", when="setting modbus tcp node", then="state not change")
def test_stopped_modbus_tcp_setting(self):
response = api.modbus_tcp_node_setting(node='modbus-tcp-1', port=502)
assert 200 == response.status_code
response = api.get_nodes_state(node='modbus-tcp-1')
assert 200 == response.status_code
assert config.NEU_NODE_STATE_STOPPED == response.json()['running']
@description(given="stopped modbus rtu node", when="setting modbus rtu node", then="state not change")
def test_stopped_modbus_rtu_setting(self):
response = api.modbus_rtu_node_setting(node='modbus-rtu-1', port=502)
assert 200 == response.status_code
response = api.get_nodes_state(node='modbus-tcp-1')
assert 200 == response.status_code
assert config.NEU_NODE_STATE_STOPPED == response.json()['running']
@description(given="stopped node", when="stop node", then="stop failed")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_stop_node_stop(self, node):
response = api.node_ctl(node=node, ctl=config.NEU_CTL_STOP)
assert 409 == response.status_code
@description(given="stopped node", when="start node", then="state is running")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_node_start(self, node):
response = api.node_ctl(node=node, ctl=config.NEU_CTL_START)
assert 200 == response.status_code
response = api.get_nodes_state(node=node)
assert 200 == response.status_code
assert config.NEU_NODE_STATE_RUNNING == response.json()['running']
@description(given="running node", when="start node", then="start failed")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_start_node_start(self, node):
response = api.node_ctl(node=node, ctl=config.NEU_CTL_START)
assert 409 == response.status_code
@description(given="create node", when="del node", then="del success")
@pytest.mark.parametrize('node', ['modbus-tcp-1', 'modbus-rtu-1'])
def test_del_node(self, node):
response = api.del_node(node=node)
assert 200 == response.status_code
+469
View File
@@ -0,0 +1,469 @@
import neuron.api as api
import neuron.error as error
import neuron.config as config
from neuron.common import *
tcp_port = random_port()
rtu_port = random_port()
@pytest.fixture(params=[('modbus-tcp', config.PLUGIN_MODBUS_TCP),
('modbus-rtu', config.PLUGIN_MODBUS_RTU)], scope='class')
def param(request):
return request.param
@pytest.fixture(autouse=True, scope='class')
def simulator_setup_teardown(param):
if param[1] == config.PLUGIN_MODBUS_TCP:
p = process.start_simulator(
['./modbus_simulator', 'tcp', f'{tcp_port}', 'ip_v4'])
else:
p = process.start_simulator(
['./modbus_simulator', 'rtu', f'{rtu_port}', 'ip_v4'])
response = api.add_node(node=param[0], plugin=param[1])
assert 200 == response.status_code
response = api.add_group(node=param[0], group='group')
assert 200 == response.status_code
if param[1] == config.PLUGIN_MODBUS_TCP:
response = api.modbus_tcp_node_setting(
node=param[0], port=tcp_port)
else:
response = api.modbus_rtu_node_setting(
node=param[0], port=rtu_port)
yield
process.stop_simulator(p)
hold_bit = [{"name": "hold_bit", "address": "1!400001.15",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BIT}]
hold_int16 = [{"name": "hold_int16", "address": "1!400001",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}]
hold_uint16 = [{"name": "hold_uint16", "address": "1!400002",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_UINT16}]
hold_int32 = [{"name": "hold_int32", "address": "1!400003",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT32}]
hold_uint32 = [{"name": "hold_uint32", "address": "1!400015",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_UINT32}]
hold_float = [{"name": "hold_float", "address": "1!400017",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_FLOAT}]
hold_string = [{"name": "hold_string", "address": "1!400020.10",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_STRING}]
hold_bytes = [{"name": "hold_bytes", "address": "1!400040.10",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BYTES}]
coil_bit_1 = [{"name": "coil_bit_1", "address": "1!000001",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BIT}]
coil_bit_2 = [{"name": "coil_bit_2", "address": "1!000002",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BIT}]
coil_bit_3 = [{"name": "coil_bit_3", "address": "1!000003",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BIT}]
coil_bit_4 = [{"name": "coil_bit_4", "address": "1!000005",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BIT}]
coil_bit_5 = [{"name": "coil_bit_5", "address": "1!000010",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BIT}]
input_bit_1 = [{"name": "input_bit_1", "address": "1!100001",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BIT}]
input_bit_2 = [{"name": "input_bit_2", "address": "1!100002",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BIT}]
input_bit_3 = [{"name": "input_bit_3", "address": "1!100003",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BIT}]
input_bit_4 = [{"name": "input_bit_4", "address": "1!100005",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BIT}]
input_bit_5 = [{"name": "input_bit_5", "address": "1!100010",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BIT}]
input_register_bit = [{"name": "input_register_bit", "address": "1!30101.15",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BIT}]
input_register_int16 = [{"name": "input_register_int16", "address": "1!30101",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_INT16}]
input_register_uint16 = [{"name": "input_register_uint16", "address": "1!30102",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_UINT16}]
input_register_int32 = [{"name": "input_register_int32", "address": "1!30103",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_INT32}]
input_register_uint32 = [{"name": "input_register_uint32", "address": "1!30115",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_UINT32}]
input_register_float = [{"name": "input_register_float", "address": "1!30117",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_FLOAT}]
input_register_string = [{"name": "input_register_string", "address": "1!30120.10",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_STRING}]
input_register_bytes = [{"name": "input_register_bytes", "address": "1!30130.10",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_BYTES}]
hold_int16_s = [{"name": "hold_int16_s", "address": "1!400001",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_STATIC, "type": config.NEU_TYPE_INT16, "value": 1}]
hold_uint16_s = [{"name": "hold_uint16_s", "address": "1!400002",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_STATIC, "type": config.NEU_TYPE_UINT16, "value": 1}]
hold_int32_s = [{"name": "hold_int32_s", "address": "1!400003",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_STATIC, "type": config.NEU_TYPE_INT32, "value": 1}]
hold_uint32_s = [{"name": "hold_uint32_s", "address": "1!400015",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_STATIC, "type": config.NEU_TYPE_UINT32, "value": 1}]
hold_float_s = [{"name": "hold_float_s", "address": "1!400017",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_STATIC, "type": config.NEU_TYPE_FLOAT, "value": 1.0}]
hold_string_s = [{"name": "hold_string_s", "address": "1!400020.10",
"attribute": config.NEU_TAG_ATTRIBUTE_RW_STATIC, "type": config.NEU_TYPE_STRING, "value": "a"}]
hold_int16_decimal = [{"name": "hold_int16_decimal", "address": "1!40103",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16, "decimal": 0.1}]
hold_uint16_decimal = [{"name": "hold_uint16_decimal", "address": "1!400105",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_UINT16, "decimal": 0.2}]
hold_int32_decimal = [{"name": "hold_int32_decimal", "address": "1!400199",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT32, "decimal": 0.3}]
hold_uint32_decimal = [{"name": "hold_uint32_decimal", "address": "1!400115",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_UINT32, "decimal": 0.3}]
hold_float_decimal = [{"name": "hold_float_decimal", "address": "1!400119",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_FLOAT, "decimal": 0.5}]
hold_double_decimal = [{"name": "hold_double_decimal", "address": "1!4000127",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_DOUBLE, "decimal": 0.6}]
hold_float_precision = [{"name": "hold_float_precision", "address": "1!4000235",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_FLOAT, "precision": 3}]
hold_double_precision = [{"name": "hold_double_precision", "address": "1!4000240",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_DOUBLE, "precision": 3}]
class TestModbus:
@description(given="created modbus node", when="add multiple tags", then="add success")
def test_add_tags(self, param):
api.add_tags_check(node=param[0], group='group', tags=hold_bit)
api.add_tags_check(node=param[0], group='group', tags=hold_int16)
api.add_tags_check(node=param[0], group='group', tags=hold_uint16)
api.add_tags_check(node=param[0], group='group', tags=hold_int32)
api.add_tags_check(node=param[0], group='group', tags=hold_uint32)
api.add_tags_check(node=param[0], group='group', tags=hold_float)
api.add_tags_check(node=param[0], group='group', tags=hold_string)
api.add_tags_check(node=param[0], group='group', tags=hold_bytes)
api.add_tags_check(
node=param[0], group='group', tags=input_register_bit)
api.add_tags_check(
node=param[0], group='group', tags=input_register_int16)
api.add_tags_check(
node=param[0], group='group', tags=input_register_uint16)
api.add_tags_check(
node=param[0], group='group', tags=input_register_int32)
api.add_tags_check(
node=param[0], group='group', tags=input_register_uint32)
api.add_tags_check(
node=param[0], group='group', tags=input_register_float)
api.add_tags_check(
node=param[0], group='group', tags=input_register_string)
api.add_tags_check(
node=param[0], group='group', tags=input_register_bytes)
api.add_tags_check(node=param[0], group='group', tags=coil_bit_1)
api.add_tags_check(node=param[0], group='group', tags=coil_bit_2)
api.add_tags_check(node=param[0], group='group', tags=coil_bit_3)
api.add_tags_check(node=param[0], group='group', tags=coil_bit_4)
api.add_tags_check(node=param[0], group='group', tags=coil_bit_5)
api.add_tags_check(node=param[0], group='group', tags=input_bit_1)
api.add_tags_check(node=param[0], group='group', tags=input_bit_2)
api.add_tags_check(node=param[0], group='group', tags=input_bit_3)
api.add_tags_check(node=param[0], group='group', tags=input_bit_4)
api.add_tags_check(node=param[0], group='group', tags=input_bit_5)
@description(given="created modbus node", when="add static tags", then="add success")
def test_add_static_tags(self, param):
api.add_tags_check(node=param[0], group='group', tags=hold_int16_s)
api.add_tags_check(node=param[0], group='group', tags=hold_uint16_s)
api.add_tags_check(node=param[0], group='group', tags=hold_int32_s)
api.add_tags_check(node=param[0], group='group', tags=hold_uint32_s)
api.add_tags_check(node=param[0], group='group', tags=hold_float_s)
api.add_tags_check(node=param[0], group='group', tags=hold_string_s)
@description(given="created modbus node", when="add wrong tags", then="add failed")
def test_add_wrong_tags(self, param):
wrong_tag1 = [{"name": "winput_bit_1", "address": "1!100001",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BIT}]
wrong_tag2 = [{"name": "winput_bit_1", "address": "1!100001",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_INT16}]
wrong_tag3 = [{"name": "whold_bytes_1", "address": "1!400001.9",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BYTES}]
wrong_tag4 = [{"name": "whold_string_1", "address": "1!400001.130",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_STRING}]
wrong_tag5 = [{"name": "whold_bytes_2", "address": "1!400001.130",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_BYTES}]
response = api.add_tags(node=param[0], group='group', tags=wrong_tag1)
assert 200 == response.status_code
assert error.NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT == response.json()[
'error']
response = api.add_tags(node=param[0], group='group', tags=wrong_tag2)
assert 200 == response.status_code
assert error.NEU_ERR_TAG_TYPE_NOT_SUPPORT == response.json()[
'error']
response = api.add_tags(node=param[0], group='group', tags=wrong_tag3)
assert 200 == response.status_code
assert error.NEU_ERR_TAG_ADDRESS_FORMAT_INVALID == response.json()[
'error']
response = api.add_tags(node=param[0], group='group', tags=wrong_tag4)
assert 200 == response.status_code
assert error.NEU_ERR_TAG_ADDRESS_FORMAT_INVALID == response.json()[
'error']
response = api.add_tags(node=param[0], group='group', tags=wrong_tag5)
assert 200 == response.status_code
assert error.NEU_ERR_TAG_ADDRESS_FORMAT_INVALID == response.json()[
'error']
@description(given="created modbus node and tags", when="write/read tags", then="write/read success")
def test_write_read_tags(self, param):
api.write_tag_check(
node=param[0], group='group', tag=hold_int16[0]['name'], value=-123)
api.write_tag_check(
node=param[0], group='group', tag=hold_uint16[0]['name'], value=123)
api.write_tag_check(
node=param[0], group='group', tag=hold_int32[0]['name'], value=-1234)
api.write_tag_check(
node=param[0], group='group', tag=hold_uint32[0]['name'], value=1234)
api.write_tag_check(
node=param[0], group='group', tag=hold_float[0]['name'], value=13.4121)
api.write_tag_check(
node=param[0], group='group', tag=hold_string[0]['name'], value='hello')
api.write_tag_check(
node=param[0], group='group', tag=hold_bytes[0]['name'], value=[0x1, 0x2, 0x3, 0x4])
api.write_tag_check(
node=param[0], group='group', tag=coil_bit_1[0]['name'], value=1)
api.write_tag_check(
node=param[0], group='group', tag=coil_bit_2[0]['name'], value=0)
api.write_tag_check(
node=param[0], group='group', tag=coil_bit_3[0]['name'], value=1)
api.write_tag_check(
node=param[0], group='group', tag=coil_bit_4[0]['name'], value=1)
api.write_tag_check(
node=param[0], group='group', tag=coil_bit_5[0]['name'], value=0)
time.sleep(0.30)
assert -123 == api.read_tag(
node=param[0], group='group', tag=hold_int16[0]['name'])
assert 123 == api.read_tag(
node=param[0], group='group', tag=hold_uint16[0]['name'])
assert -1234 == api.read_tag(
node=param[0], group='group', tag=hold_int32[0]['name'])
assert 1234 == api.read_tag(
node=param[0], group='group', tag=hold_uint32[0]['name'])
assert compare_float(13.4121, api.read_tag(
node=param[0], group='group', tag=hold_float[0]['name']))
assert 'hello' == api.read_tag(
node=param[0], group='group', tag=hold_string[0]['name'])
bytes = api.read_tag(
node=param[0], group='group', tag=hold_bytes[0]['name'])
assert len(bytes) == 10
assert bytes == [0x1, 0x2, 0x3, 0x4, 0, 0, 0, 0, 0, 0]
assert 1 == api.read_tag(
node=param[0], group='group', tag=coil_bit_1[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=coil_bit_2[0]['name'])
assert 1 == api.read_tag(
node=param[0], group='group', tag=coil_bit_3[0]['name'])
assert 1 == api.read_tag(
node=param[0], group='group', tag=coil_bit_4[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=coil_bit_5[0]['name'])
@description(given="created modbus node and tags", when="read tags", then="read success")
def test_read_tags(self, param):
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_register_bit[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_register_uint16[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_register_int16[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_register_uint32[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_register_int32[0]['name'])
compare_float(0, api.read_tag(
node=param[0], group='group', tag=input_register_float[0]['name']))
assert '' == api.read_tag(
node=param[0], group='group', tag=input_register_string[0]['name'])
bytes = api.read_tag(
node=param[0], group='group', tag=input_register_bytes[0]['name'])
assert len(bytes) == 10
assert bytes == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_bit_1[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_bit_2[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_bit_3[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_bit_4[0]['name'])
assert 0 == api.read_tag(
node=param[0], group='group', tag=input_bit_5[0]['name'])
@description(given="created modbus node, a tag with same name/address that in different groups", when="read tags", then="read success")
def test_read_tag_in_diff_group(self, param):
response = api.add_group(node=param[0], group='group1')
assert 200 == response.status_code
api.add_tags_check(node=param[0], group='group1', tags=hold_int16)
api.write_tag_check(
node=param[0], group='group', tag=hold_int16[0]['name'], value=222)
time.sleep(0.30)
assert 222 == api.read_tag(
node=param[0], group='group', tag=hold_int16[0]['name'])
assert 222 == api.read_tag(
node=param[0], group='group1', tag=hold_int16[0]['name'])
@description(given="created modbus node, a tag with same name diff address that in different groups", when="read tags", then="read success")
def test_read_tag_in_diff_address_group(self, param):
t_tag = [{"name": "t_tag", "address": "1!400031",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}]
api.add_tags_check(node=param[0], group='group1', tags=t_tag)
api.write_tag_check(
node=param[0], group='group', tag=hold_int16[0]['name'], value=333)
api.write_tag_check(
node=param[0], group='group1', tag=t_tag[0]['name'], value=444)
time.sleep(0.30)
assert 333 == api.read_tag(
node=param[0], group='group', tag=hold_int16[0]['name'])
assert 444 == api.read_tag(
node=param[0], group='group1', tag=t_tag[0]['name'])
@description(given="created modbus node/tags", when="update tags", then="update success")
def test_update_tag(self, param):
up_tag = [{"name": "up_tag", "address": "1!400031",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}]
api.add_tags_check(node=param[0], group='group', tags=up_tag)
up_tag[0]['address'] = '2!400041'
up_tag[0]['type'] = config.NEU_TYPE_FLOAT
response = api.update_tags(
node=param[0], group='group', tags=up_tag)
assert 200 == response.status_code
assert error.NEU_ERR_SUCCESS == response.json()['error']
@description(given="created modbus node/tags", when="update tag with unmatch address/type", then="update failed")
def test_update_wrong_tag(self, param):
up_tag = [{"name": "up_tag", "address": "1!400031",
"attribute": config.NEU_TAG_ATTRIBUTE_RW, "type": config.NEU_TYPE_INT16}]
up_tag[0]['address'] = '2!400041'
up_tag[0]['type'] = config.NEU_TYPE_BIT
response = api.update_tags(
node=param[0], group='group', tags=up_tag)
assert 200 == response.status_code
assert error.NEU_ERR_TAG_ATTRIBUTE_NOT_SUPPORT == response.json()[
'error']
@description(given="created modbus node", when="write tag that donot exist in neuron", then="write failed")
def test_write_not_exist_tag(self, param):
response = api.write_tag(
node=param[0], group='group', tag='not_exist', value=1)
assert 404 == response.status_code
assert error.NEU_ERR_TAG_NOT_EXIST == response.json()['error']
response = api.write_tag(
node=param[0], group='groupxx', tag='not_exist', value=1)
assert 404 == response.status_code
assert error.NEU_ERR_GROUP_NOT_EXIST == response.json()['error']
response = api.write_tag(
node="nonode", group='group', tag='not_exist', value=1)
assert 404 == response.status_code
assert error.NEU_ERR_NODE_NOT_EXIST == response.json()['error']
@description(given="created modbus node/tag", when="write only read tag", then="write failed")
def test_write_only_read_tag(self, param):
r_tag = [{"name": "r_tag", "address": "1!400031",
"attribute": config.NEU_TAG_ATTRIBUTE_READ, "type": config.NEU_TYPE_INT16}]
api.add_tags_check(node=param[0], group='group', tags=r_tag)
response = api.write_tag(
node=param[0], group='group', tag=r_tag[0]['name'], value=1)
assert 200 == response.status_code
assert error.NEU_ERR_PLUGIN_TAG_NOT_ALLOW_WRITE == response.json()[
'error']
@description(given="created modbus node/tag", when="node stopped and read/write tag", then="read/write failed")
def test_read_write_tag_stopped_node(self, param):
response = api.node_ctl(node=param[0], ctl=config.NEU_CTL_STOP)
assert 200 == response.status_code
error_code = api.read_tag_error(node=param[0], group='group',
tag=hold_int16[0]['name'])
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == error_code
response = api.write_tag(
node=param[0], group='group', tag=hold_int16[0]['name'], value=1)
assert 200 == response.status_code
assert error.NEU_ERR_PLUGIN_NOT_RUNNING == response.json()['error']
response = api.node_ctl(node=param[0], ctl=config.NEU_CTL_START)
assert 200 == response.status_code
@description(given="created modbus node", when="add decimal", then="add success")
def test_add_decimal_tag(self, param):
api.add_tags_check(
node=param[0], group='group', tags=hold_int16_decimal)
api.add_tags_check(
node=param[0], group='group', tags=hold_uint16_decimal)
api.add_tags_check(
node=param[0], group='group', tags=hold_int32_decimal)
api.add_tags_check(
node=param[0], group='group', tags=hold_uint32_decimal)
api.add_tags_check(
node=param[0], group='group', tags=hold_float_decimal)
api.add_tags_check(
node=param[0], group='group', tags=hold_double_decimal)
@description(given="created modbus node/tag", when="read/write decimal tag", then="read/write success")
def test_read_write_decimal_tag(self, param):
api.write_tag_check(
node=param[0], group='group', tag=hold_int16_decimal[0]['name'], value=11)
api.write_tag_check(
node=param[0], group='group', tag=hold_uint16_decimal[0]['name'], value=23)
api.write_tag_check(
node=param[0], group='group', tag=hold_int32_decimal[0]['name'], value=123)
api.write_tag_check(
node=param[0], group='group', tag=hold_uint32_decimal[0]['name'], value=123)
api.write_tag_check(
node=param[0], group='group', tag=hold_float_decimal[0]['name'], value=121.314)
api.write_tag_check(
node=param[0], group='group', tag=hold_double_decimal[0]['name'], value=513.11)
time.sleep(0.3)
assert 11 == api.read_tag(
node=param[0], group='group', tag=hold_int16_decimal[0]['name'])
assert 23 == api.read_tag(
node=param[0], group='group', tag=hold_uint16_decimal[0]['name'])
assert 123 == api.read_tag(
node=param[0], group='group', tag=hold_int32_decimal[0]['name'])
assert 123 == api.read_tag(
node=param[0], group='group', tag=hold_uint32_decimal[0]['name'])
compare_float(121.314, api.read_tag(
node=param[0], group='group', tag=hold_float_decimal[0]['name']))
assert 513.11 == api.read_tag(
node=param[0], group='group', tag=hold_double_decimal[0]['name'])
@description(given="created modbus node", when="add precision tag", then="add success")
def test_add_precision_tag(self, param):
api.add_tags_check(
node=param[0], group='group', tags=hold_float_precision)
api.add_tags_check(
node=param[0], group='group', tags=hold_double_precision)
@description(given="created modbus node/tag", when="read/write precision tag", then="read/write success")
def test_read_write_precision_tag(self, param):
api.write_tag_check(
node=param[0], group='group', tag=hold_float_precision[0]['name'], value=121.3149121)
api.write_tag_check(
node=param[0], group='group', tag=hold_double_precision[0]['name'], value=513.1279112)
time.sleep(0.3)
compare_float(121.314, api.read_tag(
node=param[0], group='group', tag=hold_float_precision[0]['name']))
compare_float(513.127, api.read_tag(
node=param[0], group='group', tag=hold_double_precision[0]['name']))
+15 -15
View File
@@ -10,7 +10,7 @@ class TestLog:
@description(given="node", when="change log_level to debug", then="change success")
def test_change_log_level_debug(self):
response = api.add_node(node='modbus-tcp-1', plugin=modbus_tcp)
response = api.add_node(node='modbus-tcp-1', plugin=PLUGIN_MODBUS_TCP)
assert 200 == response.status_code
assert 0 == response.json()['error']
@@ -18,54 +18,54 @@ class TestLog:
assert 200 == response.status_code
assert 0 == response.json()['error']
response = api.get_nodes_state()
response = api.get_nodes_state('modbus-tcp-1')
assert 200 == response.status_code
assert "debug" == response.json()['states'][0]['log_level']
assert "debug" == response.json()['log_level']
@description(given="node", when="change log_level to info", then="change success")
def test_change_log_level_info(self):
response = api.change_log_level(node='modbus-tcp-1', level='info')
assert 0 == response.json()['error']
response = api.get_nodes_state()
response = api.get_nodes_state('modbus-tcp-1')
assert 200 == response.status_code
assert "info" == response.json()['states'][0]['log_level']
assert "info" == response.json()['log_level']
@description(given="node", when="change log_level to warn", then="change success")
def test_change_log_level_warn(self):
response = api.change_log_level(node='modbus-tcp-1', level='warn')
assert 0 == response.json()['error']
response = api.get_nodes_state()
response = api.get_nodes_state('modbus-tcp-1')
assert 200 == response.status_code
assert "warn" == response.json()['states'][0]['log_level']
assert "warn" == response.json()['log_level']
@description(given="node", when="change log_level to error", then="change success")
def test_change_log_level_error(self):
response = api.change_log_level(node='modbus-tcp-1', level='error')
assert 0 == response.json()['error']
response = api.get_nodes_state()
response = api.get_nodes_state('modbus-tcp-1')
assert 200 == response.status_code
assert "error" == response.json()['states'][0]['log_level']
assert "error" == response.json()['log_level']
@description(given="node", when="change log_level to fatal", then="change success")
def test_change_log_level_fatal(self):
response = api.change_log_level(node='modbus-tcp-1', level='fatal')
assert 0 == response.json()['error']
response = api.get_nodes_state()
response = api.get_nodes_state('modbus-tcp-1')
assert 200 == response.status_code
assert "fatal" == response.json()['states'][0]['log_level']
assert "fatal" == response.json()['log_level']
@description(given="node", when="change log_level to notice", then="change success")
def test_change_log_level_notice(self):
response = api.change_log_level(node='modbus-tcp-1', level='notice')
assert 0 == response.json()['error']
response = api.get_nodes_state()
response = api.get_nodes_state('modbus-tcp-1')
assert 200 == response.status_code
assert "notice" == response.json()['states'][0]['log_level']
assert "notice" == response.json()['log_level']
@description(given="node", when="change log_level to invalid level", then="change failed")
def test_change_log_level_invalid(self):
@@ -73,6 +73,6 @@ class TestLog:
assert 400 == response.status_code
assert 1003 == response.json()['error']
response = api.get_nodes_state()
response = api.get_nodes_state('modbus-tcp-1')
assert 200 == response.status_code
assert "notice" == response.json()['states'][0]['log_level']
assert "notice" == response.json()['log_level']
+3
View File
@@ -0,0 +1,3 @@
import sys
sys.path.append("tests/ft")
+20
View File
@@ -0,0 +1,20 @@
import neuron.api as api
from neuron.common import *
@pytest.fixture(autouse=True, scope='class')
def simulator_setup_teardown():
port = random_port()
p = process.start_simulator(
['./modbus_simulator', 'tcp', f'{port}', 'ip_v4'])
yield
process.stop_simulator(p)
class TestModbusTCP:
@description(given="name and password", when="login", then="login success with token")
def test_login_success(self):
response = api.login()
assert 200 == response.status_code
+128 -2
View File
@@ -1,5 +1,6 @@
import requests
import neuron.config as config
import neuron.error as error
def login(user='admin', password='0000'):
@@ -17,11 +18,136 @@ def get_license(jwt=config.default_jwt):
def upload_license(license, jwt=config.default_jwt):
return requests.post(url=config.BASE_URL + '/api/v2/license', headers={"Authorization": jwt}, json={"license": license})
def change_log_level(node, level, jwt=config.default_jwt):
return requests.put(url=config.BASE_URL + '/api/v2/log/level', headers={"Authorization": jwt}, json={"node": node, "level": level})
def add_node(node, plugin, jwt=config.default_jwt):
return requests.post(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, json={"name": node, "plugin": plugin})
def get_nodes_state(jwt=config.default_jwt):
return requests.get(url=config.BASE_URL + '/api/v2/node/state', headers={"Authorization": jwt})
def del_node(node, jwt=config.default_jwt):
return requests.delete(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, json={"name": node})
def get_nodes(type, jwt=config.default_jwt):
return requests.get(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, params={"type": type})
def node_ctl(node, ctl, jwt=config.default_jwt):
return requests.post(url=config.BASE_URL + '/api/v2/node/ctl', headers={"Authorization": jwt}, json={"node": node, "cmd": ctl})
def get_nodes_state(node, jwt=config.default_jwt):
return requests.get(url=config.BASE_URL + '/api/v2/node/state', headers={"Authorization": jwt}, params={"node": node})
def node_setting(node, json, jwt=config.default_jwt):
return requests.post(url=config.BASE_URL + '/api/v2/node/setting', headers={"Authorization": jwt}, json={"node": node, "params": json})
def get_node_setting(node, jwt=config.default_jwt):
return requests.get(url=config.BASE_URL + '/api/v2/node/setting', headers={"Authorization": jwt}, params={"node": node})
def add_group(node, group, interval=100):
return requests.post(url=config.BASE_URL + '/api/v2/group', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "interval": interval})
def del_group(node, group):
return requests.delete(url=config.BASE_URL + '/api/v2/group', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group})
def update_group(node, group, new_name="", interval=0):
if len(new_name) > 0 and interval > 0:
return requests.put(url=config.BASE_URL + '/api/v2/group', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "new_name": new_name, "interval": interval})
elif len(new_name) > 0:
return requests.put(url=config.BASE_URL + '/api/v2/group', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "new_name": new_name})
elif interval > 0:
return requests.put(url=config.BASE_URL + '/api/v2/group', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "interval": interval})
else:
assert False
def add_tags(node, group, tags):
return requests.post(url=config.BASE_URL + '/api/v2/tags', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "tags": tags})
def add_tags_check(node, group, tags):
response = add_tags(node=node, group=group, tags=tags)
assert 200 == response.status_code
assert error.NEU_ERR_SUCCESS == response.json()['error']
def del_tags(node, group, tags):
return requests.delete(url=config.BASE_URL + '/api/v2/tags', headers={"Authorizatioin": config.default_jwt}, json={"node": node, "group": group, "tags": tags})
def update_tags(node, group, tags):
return requests.put(url=config.BASE_URL + '/api/v2/tags', headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "tags": tags})
def get_tags(node, group):
return requests.get(url=config.BASE_URL + "/api/v2/tags", headers={"Authorization": config.default_jwt}, params={"node": node, "group": group})
def read_tags(node, group):
return requests.post(url=config.BASE_URL + "/api/v2/read", headers={"Authorization": config.default_jwt}, json={"node": node, "group": group})
def read_tag(node, group, tag):
response = read_tags(node, group)
assert 200 == response.status_code
x = list(filter(lambda x: x['name'] == tag,
response.json()['tags']))
assert len(x) == 1
try:
x[0]['value']
except KeyError:
print(x[0])
finally:
return x[0]['value']
def read_tag_error(node, group, tag):
response = read_tags(node, group)
assert 200 == response.status_code
x = list(filter(lambda x: x['name'] == tag,
response.json()['tags']))
assert len(x) == 1
try:
x[0]['error']
except KeyError:
print(x[0])
finally:
return x[0]['error']
def write_tag(node, group, tag, value):
return requests.post(url=config.BASE_URL + "/api/v2/write", headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "tag": tag, "value": value})
def write_tag_check(node, group, tag, value):
response = write_tag(node, group, tag, value)
assert 200 == response.status_code
assert error.NEU_ERR_SUCCESS == response.json()['error']
def write_tags(node, group, tag_values):
return requests.post(url=config.BASE_URL + "/api/v2/writes", headers={"Authorization": config.default_jwt}, json={"node": node, "group": group, "tags": tag_values})
# plugin setting
def modbus_tcp_node_setting(node, port, connection_mode=0, transport_mode=0, interval=0, host='127.0.0.1', timeout=3000):
return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode, "interval": interval,
"host": host, "port": port, "timeout": timeout})
def modbus_rtu_node_setting(node, port, connection_mode=0, transport_mode=0, interval=10, host='127.0.0.1', timeout=3000, link=1, device="", stop=0, parity=0, baud=4, data=3):
return node_setting(node, json={"connection_mode": connection_mode, "transport_mode": transport_mode,
"interval": interval, "host": host, "port": port, "timeout": timeout,
"link": link, "device": device, "stop": stop, "parity": parity,
"baud": baud, "data": data})
+9 -1
View File
@@ -1,6 +1,6 @@
import time
import sys
from functools import wraps
import random
import pytest
@@ -25,6 +25,14 @@ class description(object):
return wrapper
def random_port():
return random.randint(30000, 65535)
def compare_float(v1, v2, delta=0.001):
return abs(v1 - v2) < delta
@pytest.fixture(autouse=True, scope='class')
def class_setup_and_teardown():
process.remove_persistence()
+68 -1
View File
@@ -1,3 +1,70 @@
BASE_URL = "http://127.0.0.1:7000"
default_jwt = "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJuZXVyb24iLCJib2R5RW5jb2RlIjowLCJleHAiOjE3MTc4MzUyNjIsImlhdCI6MTY4NjI5OTI2MiwiaXNzIjoibmV1cm9uIn0.tJ8Z12S5lzzyqvJedFr11w0FmQ8l9inFHuzcuA_3uKoNBJSZlQAkcWyDAO2XELyuZFtHPrk8pJFgEqTzwphtBAybVXbeHBRWED5XuHvYqznzwk1J2UCOuw_ehmHnLszZHRAcMoeLWIRIx0KM7BXvZAyFA2J1axJntxfRrurNMn6MbfnGGtza6hJfuQ6pG-h4cHhrBOogf8nw3f8RLfd16vbWobhEp8KBUrwsfn2Iv4hMXvZMekv_PXboLO74f7oMkEL6pdM9g6G6rDBTjTU8FssfeyJcAP7Xb9mS2G7GNW5B8twtPVLtpOQH9VNbLa4OQxdMb0WN86i9vSDiCOoN6A"
modbus_tcp = "Modbus TCP"
NEU_NODE_DRIVER = 1
NEU_NODE_APP = 2
NEU_CTL_START = 0
NEU_CTL_STOP = 1
NEU_NODE_STATE_INIT = 1
NEU_NODE_STATE_READY = 2
NEU_NODE_STATE_RUNNING = 3
NEU_NODE_STATE_STOPPED = 4
NEU_NODE_LINK_STATE_DISCONNECTED = 0
NEU_NODE_LINK_STATE_CONNECTED = 1
NEU_TAG_ATTRIBUTE_READ = 1
NEU_TAG_ATTRIBUTE_WRITE = 2
NEU_TAG_ATTRIBUTE_SUBSCRIBE = 4
NEU_TAG_ATTRIBUTE_STATIC = 8
NEU_TAG_ATTRIBUTE_RW = NEU_TAG_ATTRIBUTE_READ | NEU_TAG_ATTRIBUTE_WRITE
NEU_TAG_ATTRIBUTE_RW_STATIC = NEU_TAG_ATTRIBUTE_RW | NEU_TAG_ATTRIBUTE_STATIC
NEU_TYPE_INT8 = 1
NEU_TYPE_UINT8 = 2
NEU_TYPE_INT16 = 3
NEU_TYPE_UINT16 = 4
NEU_TYPE_INT32 = 5
NEU_TYPE_UINT32 = 6
NEU_TYPE_INT64 = 7
NEU_TYPE_UINT64 = 8
NEU_TYPE_FLOAT = 9
NEU_TYPE_DOUBLE = 10
NEU_TYPE_BIT = 11
NEU_TYPE_BOOL = 12
NEU_TYPE_STRING = 13
NEU_TYPE_BYTES = 14
NEU_TYPE_ERROR = 15
NEU_TYPE_WORD = 16
NEU_TYPE_DWORD = 17
NEU_TYPE_LWORD = 18
NEU_BAUD_115200 = 0
NEU_BAUD_57600 = 1
NEU_BAUD_38400 = 2
NEU_BAUD_19200 = 3
NEU_BAUD_9600 = 4
NEU_BAUD_4800 = 5
NEU_BAUD_2400 = 6
NEU_BAUD_1800 = 7
NEU_BAUD_1200 = 8
NEU_BAUD_600 = 9
NEU_PARITY_NONE = 0
NEU_PARITY_ODD = 1
NEU_PARITY_EVEN = 2
NEU_PARITY_MARK = 3
NEU_PARITY_SPACE = 4
NEU_STOP_1 = 0
NEU_STOP_2 = 1
NEU_DATA_5 = 0
NEU_DATA_6 = 1
NEU_DATA_7 = 2
NEU_DATA_8 = 3
PLUGIN_MODBUS_TCP = "Modbus TCP"
PLUGIN_MODBUS_RTU = "Modbus RTU"
-6
View File
@@ -1,8 +1,6 @@
import os
import time
import pytest
import subprocess
import random
def remove_persistence(dir='build/'):
@@ -34,7 +32,3 @@ def start_simulator(args, dir='build/simulator'):
def stop_simulator(process):
process.terminate()
def random_port():
return random.randint(30000, 65535)
+1 -1
View File
@@ -1,4 +1,4 @@
from distutils.core import setup
setup(name='neuronft', version="0.0.1",
setup(name='neuronft', version="0.0.2",
description='ft module', author='neuron', py_modules=['neuron.api', 'neuron.common', 'neuron.config', 'neuron.process', 'neuron.error'])
+1 -1
View File
@@ -1 +1 @@
2.6.0-dev
2.7.0-dev