Working on POC-108. Reading holding registers confirmed working

This commit is contained in:
Patrick McDonagh
2017-01-05 17:20:44 -06:00
parent 3ebeaf7b0b
commit 726b00ad9a
9 changed files with 568 additions and 85 deletions

BIN
Modbus Map.xlsx Normal file

Binary file not shown.

6
README.md Normal file
View File

@@ -0,0 +1,6 @@
# Modbus Register Map
## Coils
Reg. # | Description | Access |
1 |

149
analog.json Normal file
View File

@@ -0,0 +1,149 @@
[
{"tag_name": "_Firmware_Rev", "register_type": "ir", "register_number": 1, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "_Program_Firmware", "register_type": "ir", "register_number": 6, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Card_Type", "register_type": "ir", "register_number": 11, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Downhole_AdjustedGrossStroke", "register_type": "ir", "register_number": 16, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Downhole_FluidLoad", "register_type": "ir", "register_number": 21, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Downhole_GrossStroke", "register_type": "ir", "register_number": 26, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Downhole_Max_Load.Load", "register_type": "ir", "register_number": 31, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Downhole_Max_Position.Position", "register_type": "ir", "register_number": 36, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Downhole_Min_Load.Load", "register_type": "ir", "register_number": 41, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Downhole_Min_Position.Position", "register_type": "ir", "register_number": 46, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Downhole_NetStroke", "register_type": "ir", "register_number": 51, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Fillage_Percent", "register_type": "ir", "register_number": 56, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Fluid_Above_Pump", "register_type": "ir", "register_number": 61, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Fluid_Moved", "register_type": "ir", "register_number": 66, "scale_type": 0, "scale_multiplier": 10000},
{"tag_name": "Card_Past[1].ID", "register_type": "ir", "register_number": 71, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Num_Points", "register_type": "ir", "register_number": 76, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Polished_Rod_HP", "register_type": "ir", "register_number": 81, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Pump_HP", "register_type": "ir", "register_number": 86, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Pump_Intake_Pressure", "register_type": "ir", "register_number": 91, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].SPM", "register_type": "ir", "register_number": 96, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Card_Past[1].Surface_Max.Load", "register_type": "ir", "register_number": 101, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Surface_Max.Position", "register_type": "ir", "register_number": 106, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Surface_Min.Load", "register_type": "ir", "register_number": 111, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[1].Surface_Min.Position", "register_type": "ir", "register_number": 116, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Surface_StrokeLength", "register_type": "ir", "register_number": 121, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[1].Tubing_Movement", "register_type": "ir", "register_number": 126, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Card_Type", "register_type": "ir", "register_number": 131, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Downhole_AdjustedGrossStroke", "register_type": "ir", "register_number": 136, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Downhole_FluidLoad", "register_type": "ir", "register_number": 141, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Downhole_GrossStroke", "register_type": "ir", "register_number": 146, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Downhole_Max_Load.Load", "register_type": "ir", "register_number": 151, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Downhole_Max_Position.Position", "register_type": "ir", "register_number": 156, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Downhole_Min_Load.Load", "register_type": "ir", "register_number": 161, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Downhole_Min_Position.Position", "register_type": "ir", "register_number": 166, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Downhole_NetStroke", "register_type": "ir", "register_number": 171, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Fillage_Percent", "register_type": "ir", "register_number": 176, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Fluid_Above_Pump", "register_type": "ir", "register_number": 181, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Fluid_Moved", "register_type": "ir", "register_number": 186, "scale_type": 0, "scale_multiplier": 10000},
{"tag_name": "Card_Past[2].ID", "register_type": "ir", "register_number": 191, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Num_Points", "register_type": "ir", "register_number": 196, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Polished_Rod_HP", "register_type": "ir", "register_number": 201, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Pump_HP", "register_type": "ir", "register_number": 206, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Pump_Intake_Pressure", "register_type": "ir", "register_number": 211, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].SPM", "register_type": "ir", "register_number": 216, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Card_Past[2].Surface_Max.Load", "register_type": "ir", "register_number": 221, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Surface_Max.Position", "register_type": "ir", "register_number": 226, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Surface_Min.Load", "register_type": "ir", "register_number": 231, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[2].Surface_Min.Position", "register_type": "ir", "register_number": 236, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Surface_StrokeLength", "register_type": "ir", "register_number": 241, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[2].Tubing_Movement", "register_type": "ir", "register_number": 246, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Card_Type", "register_type": "ir", "register_number": 251, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Downhole_AdjustedGrossStroke", "register_type": "ir", "register_number": 256, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Downhole_FluidLoad", "register_type": "ir", "register_number": 261, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Downhole_GrossStroke", "register_type": "ir", "register_number": 266, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Downhole_Max_Load.Load", "register_type": "ir", "register_number": 271, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Downhole_Max_Position.Position", "register_type": "ir", "register_number": 276, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Downhole_Min_Load.Load", "register_type": "ir", "register_number": 281, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Downhole_Min_Position.Position", "register_type": "ir", "register_number": 286, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Downhole_NetStroke", "register_type": "ir", "register_number": 291, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Fillage_Percent", "register_type": "ir", "register_number": 296, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Fluid_Above_Pump", "register_type": "ir", "register_number": 301, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Fluid_Moved", "register_type": "ir", "register_number": 306, "scale_type": 0, "scale_multiplier": 10000},
{"tag_name": "Card_Past[3].ID", "register_type": "ir", "register_number": 311, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Num_Points", "register_type": "ir", "register_number": 316, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Polished_Rod_HP", "register_type": "ir", "register_number": 321, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Pump_HP", "register_type": "ir", "register_number": 326, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Pump_Intake_Pressure", "register_type": "ir", "register_number": 331, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].SPM", "register_type": "ir", "register_number": 336, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Card_Past[3].Surface_Max.Load", "register_type": "ir", "register_number": 341, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Surface_Max.Position", "register_type": "ir", "register_number": 346, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Surface_Min.Load", "register_type": "ir", "register_number": 351, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[3].Surface_Min.Position", "register_type": "ir", "register_number": 356, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Surface_StrokeLength", "register_type": "ir", "register_number": 361, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[3].Tubing_Movement", "register_type": "ir", "register_number": 366, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Card_Type", "register_type": "ir", "register_number": 371, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Downhole_AdjustedGrossStroke", "register_type": "ir", "register_number": 376, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Downhole_FluidLoad", "register_type": "ir", "register_number": 381, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Downhole_GrossStroke", "register_type": "ir", "register_number": 386, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Downhole_Max_Load.Load", "register_type": "ir", "register_number": 391, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Downhole_Max_Position.Position", "register_type": "ir", "register_number": 396, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Downhole_Min_Load.Load", "register_type": "ir", "register_number": 401, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Downhole_Min_Position.Position", "register_type": "ir", "register_number": 406, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Downhole_NetStroke", "register_type": "ir", "register_number": 411, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Fillage_Percent", "register_type": "ir", "register_number": 416, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Fluid_Above_Pump", "register_type": "ir", "register_number": 421, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Fluid_Moved", "register_type": "ir", "register_number": 426, "scale_type": 0, "scale_multiplier": 10000},
{"tag_name": "Card_Past[4].ID", "register_type": "ir", "register_number": 431, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Num_Points", "register_type": "ir", "register_number": 436, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Polished_Rod_HP", "register_type": "ir", "register_number": 441, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Pump_HP", "register_type": "ir", "register_number": 446, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Pump_Intake_Pressure", "register_type": "ir", "register_number": 451, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].SPM", "register_type": "ir", "register_number": 456, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Card_Past[4].Surface_Max.Load", "register_type": "ir", "register_number": 461, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Surface_Max.Position", "register_type": "ir", "register_number": 466, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Surface_Min.Load", "register_type": "ir", "register_number": 471, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Card_Past[4].Surface_Min.Position", "register_type": "ir", "register_number": 476, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Surface_StrokeLength", "register_type": "ir", "register_number": 481, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Card_Past[4].Tubing_Movement", "register_type": "ir", "register_number": 486, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Drive_Speed_Reference_SP", "register_type": "ir", "register_number": 491, "scale_type": 0, "scale_multiplier": 10},
{"tag_name": "Drive_Torque_Percent", "register_type": "ir", "register_number": 496, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Average_SPM", "register_type": "ir", "register_number": 501, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "GAUGEOFF_Downhole_GrossStroke", "register_type": "ir", "register_number": 506, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Downhole_NetStroke", "register_type": "ir", "register_number": 511, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Electricity_Cost", "register_type": "ir", "register_number": 516, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Fluid_Above_Pump", "register_type": "ir", "register_number": 521, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Inflow_Rate", "register_type": "ir", "register_number": 526, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_kWh", "register_type": "ir", "register_number": 531, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_kWh_Regen", "register_type": "ir", "register_number": 536, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Lifting_Cost", "register_type": "ir", "register_number": 541, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Max_Load", "register_type": "ir", "register_number": 546, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "GAUGEOFF_Min_Load", "register_type": "ir", "register_number": 551, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "GAUGEOFF_Percent_Run", "register_type": "ir", "register_number": 556, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Polished_Rod_HP", "register_type": "ir", "register_number": 561, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Pump_Intake_Pressure", "register_type": "ir", "register_number": 566, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Surface_StrokeLength", "register_type": "ir", "register_number": 571, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "GAUGEOFF_Tubing_Movement", "register_type": "ir", "register_number": 576, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Gearbox_Loading", "register_type": "ir", "register_number": 581, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Gearbox_Torque", "register_type": "ir", "register_number": 586, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Input_Analog_1_AIN.Val", "register_type": "ir", "register_number": 591, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Input_Analog_2_AIN.Val", "register_type": "ir", "register_number": 596, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Input_Analog_3_AIN.Val", "register_type": "ir", "register_number": 601, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Instantaneous_SPM", "register_type": "ir", "register_number": 606, "scale_type": 0, "scale_multiplier": 10},
{"tag_name": "kWh_Today", "register_type": "ir", "register_number": 611, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Max_Theoretical_Fluid_Load", "register_type": "ir", "register_number": 616, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Motor_Torque", "register_type": "ir", "register_number": 621, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "_dt", "register_type": "hr", "register_number": 1, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Casing_ID", "register_type": "hr", "register_number": 6, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Drive_Start_Speed", "register_type": "hr", "register_number": 11, "scale_type": 0, "scale_multiplier": 10},
{"tag_name": "Electricity_Cost", "register_type": "hr", "register_number": 16, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Estimated_Tubing_Movement", "register_type": "hr", "register_number": 21, "scale_type": 0, "scale_multiplier": 100},
{"tag_name": "Fluid_Gradient", "register_type": "hr", "register_number": 26, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Friction", "register_type": "hr", "register_number": 31, "scale_type": 0, "scale_multiplier": 10},
{"tag_name": "Gauge_Off_Time.Hour", "register_type": "hr", "register_number": 36, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Gauge_Off_Time.Min", "register_type": "hr", "register_number": 41, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Analog_1_AIN.Cfg_PVEUMax", "register_type": "hr", "register_number": 46, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Analog_1_AIN.Cfg_PVEUMin", "register_type": "hr", "register_number": 51, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Analog_2_AIN.Cfg_PVEUMax", "register_type": "hr", "register_number": 56, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Analog_2_AIN.Cfg_PVEUMin", "register_type": "hr", "register_number": 61, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Analog_3_AIN.Cfg_PVEUMax", "register_type": "hr", "register_number": 66, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Analog_3_AIN.Cfg_PVEUMin", "register_type": "hr", "register_number": 71, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Inclinometer_AIN.Cfg_PVEUMax", "register_type": "hr", "register_number": 76, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_Inclinometer_AIN.Cfg_PVEUMin", "register_type": "hr", "register_number": 81, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_LoadCell_AIN.Cfg_PVEUMax", "register_type": "hr", "register_number": 86, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "Input_LoadCell_AIN.Cfg_PVEUMin", "register_type": "hr", "register_number": 91, "scale_type": 0, "scale_multiplier": 1},
{"tag_name": "K_Factor", "register_type": "hr", "register_number": 96, "scale_type": 0, "scale_multiplier": 1000},
{"tag_name": "Min_Fluid_Load_Shutdown_Setpoint", "register_type": "hr", "register_number": 101, "scale_type": 0, "scale_multiplier": 1}
]

4
arraylist.json Normal file
View File

@@ -0,0 +1,4 @@
[
]

31
digital.json Normal file
View File

@@ -0,0 +1,31 @@
[
{"tag_name": "_TOC_ACCEPTED", "register_type": "co", "register_number": 1},
{"tag_name": "Autotune_Next_Start", "register_type": "co", "register_number": 2},
{"tag_name": "Gas_Interference_Override_Enabled", "register_type": "co", "register_number": 3},
{"tag_name": "Gauge_Off_Manual", "register_type": "co", "register_number": 4},
{"tag_name": "Initialize", "register_type": "co", "register_number": 5},
{"tag_name": "Input_Analog_1.Channel", "register_type": "co", "register_number": 6},
{"tag_name": "Input_Analog_1.Enabled", "register_type": "co", "register_number": 7},
{"tag_name": "Input_Analog_1.Type", "register_type": "co", "register_number": 8},
{"tag_name": "Input_Analog_2.Channel", "register_type": "co", "register_number": 9},
{"tag_name": "Input_Analog_2.Enabled", "register_type": "co", "register_number": 10},
{"tag_name": "Input_Analog_2.Type", "register_type": "co", "register_number": 11},
{"tag_name": "Input_Analog_3.Channel", "register_type": "co", "register_number": 12},
{"tag_name": "Input_Analog_3.Enabled", "register_type": "co", "register_number": 13},
{"tag_name": "Input_Analog_3.Type", "register_type": "co", "register_number": 14},
{"tag_name": "Input_Inclinometer_Calibrate", "register_type": "co", "register_number": 15},
{"tag_name": "Input_Inclinometer.Channel", "register_type": "co", "register_number": 16},
{"tag_name": "Input_Inclinometer.Enabled", "register_type": "co", "register_number": 17},
{"tag_name": "Input_Inclinometer.Type", "register_type": "co", "register_number": 18},
{"tag_name": "Input_LoadCell.Channel", "register_type": "co", "register_number": 19},
{"tag_name": "Input_LoadCell.Enabled", "register_type": "co", "register_number": 20},
{"tag_name": "Input_LoadCell.Type", "register_type": "co", "register_number": 21},
{"tag_name": "Min_Fluid_Load_Shutdown_Enabled", "register_type": "co", "register_number": 22},
{"tag_name": "Restart_After_Fault_Allowed", "register_type": "co", "register_number": 23},
{"tag_name": "Update_Tapers", "register_type": "co", "register_number": 24},
{"tag_name": "USE_WIRELESS_LOADCELL", "register_type": "co", "register_number": 25},
{"tag_name": "Write_Mode_Data", "register_type": "co", "register_number": 26},
{"tag_name": "Write_Setup_Data", "register_type": "co", "register_number": 27},
{"tag_name": "Inclinometer_Calibrating", "register_type": "di", "register_number": 1},
{"tag_name": "Inclinometer_Stale", "register_type": "di", "register_number": 2}
]

90
plc_to_mongo.py Normal file
View File

@@ -0,0 +1,90 @@
import pymongo
import json
from time import sleep
from time import time as now
from pymongo import MongoClient
import pycomm_helper.utils as plc
PLC_IP_ADDRESS = '10.20.4.7'
def main():
client = MongoClient()
db = client.tag_data
tag_vals = db.tag_vals
print("THERE ARE ALREADY {} VALUES IN tag_vals".format(tag_vals.count()))
with open('analog.json', 'rb') as analogfile:
analog_list = json.loads(analogfile.read())
with open('digital.json', 'rb') as digitalfile:
digital_list = json.loads(digitalfile.read())
with open('arraylist.json', 'rb') as arrayfile:
arr_list = [] # json.loads(arrayfile.read())
for entry in analog_list + digital_list + arr_list:
if tag_vals.find({'tag_name': entry['tag_name']}).count() < 1:
tag_vals.insert(entry)
print("NOW THERE ARE {} VALUES IN tag_vals".format(tag_vals.count()))
while True:
for t in analog_list:
try:
plc_val = plc.readTag(PLC_IP_ADDRESS, t['tag_name'])
if plc_val:
t['tag_type'] = plc_val[1]
t['val_actual'] = plc_val[0]
t['timestamp'] = now()
if int(t['scale_type']) == 0:
t['val'] = int(plc_val[0] * t['scale_multiplier'])
else:
t['val'] = int(plc_val[0] / t['scale_multiplier'])
tag_vals.update({'tag_name': t['tag_name']}, t)
print("Updated: {}".format(tag_vals.find({'tag_name': t['tag_name']})[0]))
except Exception as e:
print("[ERROR] {} - {}".format(t['tag_name'], e))
for t in digital_list:
try:
plc_val = plc.readTag(PLC_IP_ADDRESS, t['tag_name'])
if plc_val:
t['tag_type'] = plc_val[1]
t['val'] = plc_val[0]
t['timestamp'] = now()
tag_vals.update({'tag_name': t['tag_name']}, t)
print("Updated: {}".format(tag_vals.find({'tag_name': t['tag_name']})[0]))
except Exception as e:
print("[ERROR] {} - {}".format(t['tag_name'], e))
for a in arr_list:
try:
plc_val = plc.readArray(PLC_IP_ADDRESS, str(a['tag_name']), int(a['length']))
if plc_val:
a['val'] = plc_val
a['tag_type'] = 'ARRAY'
t['timestamp'] = now()
tag_vals.update({'tag_name': a['tag_name']}, a)
print("Updated: {}".format(tag_vals.find({'tag_name': a['tag_name']})[0]))
except Exception as e:
print("[ERROR] {} - {}".format(a['tag_name'], e))
sleep(5)
def purge():
client = MongoClient()
db = client.tag_data
tag_vals = db.tag_vals
tag_vals.delete_many({})
print("THERE ARE {} VALUES IN tag_vals".format(tag_vals.count()))
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
if sys.argv[1] == 'purge':
print("Purging...")
purge()
else:
main()

View File

@@ -1,85 +0,0 @@
#!/usr/bin/env python3
'''
Pymodbus Server With Updating Thread
--------------------------------------------------------------------------
This is an example of having a background thread updating the
context while the server is operating. This can also be done with
a python thread::
from threading import Thread
thread = Thread(target=updating_writer, args=(context,))
thread.start()
'''
# ---------------------------------------------------------------------------#
# import the modbus libraries we need
# ---------------------------------------------------------------------------#
from pymodbus.server.async import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
# from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer
# ---------------------------------------------------------------------------#
# import the twisted libraries we need
# ---------------------------------------------------------------------------#
from twisted.internet.task import LoopingCall
# ---------------------------------------------------------------------------#
# configure the service logging
# ---------------------------------------------------------------------------#
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
# ---------------------------------------------------------------------------#
# define your callback process
# ---------------------------------------------------------------------------#
def updating_writer(a):
''' A worker process that runs every so often and
updates live values of the context. It should be noted
that there is a race condition for the update.
:param arguments: The input arguments to the call
'''
log.debug("updating the context")
context = a[0]
register = 3
slave_id = 0x00
address = 0x10
values = context[slave_id].getValues(register, address, count=5)
values = [v + 1 for v in values]
log.debug("new values: " + str(values))
context[slave_id].setValues(register, address, values)
# ---------------------------------------------------------------------------#
# initialize your data store
# ---------------------------------------------------------------------------#
store = ModbusSlaveContext(
di=ModbusSequentialDataBlock(0, [17]*100),
co=ModbusSequentialDataBlock(0, [17]*100),
hr=ModbusSequentialDataBlock(0, [17]*100),
ir=ModbusSequentialDataBlock(0, [17]*100))
context = ModbusServerContext(slaves=store, single=True)
# ---------------------------------------------------------------------------#
# initialize the server information
# ---------------------------------------------------------------------------#
identity = ModbusDeviceIdentification()
identity.VendorName = 'pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'
# ---------------------------------------------------------------------------#
# run the server you want
# ---------------------------------------------------------------------------#
time = 5 # 5 seconds delay
loop = LoopingCall(f=updating_writer, a=(context,))
loop.start(time, now=False) # initially delay by time
StartTcpServer(context, identity=identity, address=("localhost", 5020))

209
poc_to_modbus.py Normal file
View File

@@ -0,0 +1,209 @@
#!/usr/bin/env python
'''
Pymodbus Server With Callbacks
--------------------------------------------------------------------------
This is an example of adding callbacks to a running modbus server
when a value is written to it. In order for this to work, it needs
a device-mapping file.
'''
# ---------------------------------------------------------------------------#
# import the modbus libraries we need
# ---------------------------------------------------------------------------#
from pymodbus.server.async import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer
# ---------------------------------------------------------------------------#
# import the python libraries we need
# ---------------------------------------------------------------------------#
import pymongo
from pymongo import MongoClient
from pycomm_helper import utils as plc
from time import time as now
# ---------------------------------------------------------------------------#
# configure the service logging
# ---------------------------------------------------------------------------#
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
PLC_IP_ADDRESS = '10.20.4.7'
def getTagsFromDB():
client = MongoClient()
db = client.tag_data
tags = db.tag_vals
print("Found {} tags in the database".format(tags.count()))
di_tags_cur = tags.find({'register_type': 'di'})
di_tags = list(di_tags_cur)
di_tags_num = di_tags_cur.count()
print("{} Digital Inputs".format(di_tags_num))
co_tags_cur = tags.find({'register_type': 'co'})
co_tags = list(co_tags_cur)
co_tags_num = co_tags_cur.count()
print("{} Coils".format(co_tags_num))
ir_tags_cur = tags.find({'register_type': 'ir'})
ir_tags = list(ir_tags_cur)
ir_tags_num = ir_tags_cur.count()
print("{} Input Registers".format(ir_tags_num))
hr_tags_cur = tags.find({'register_type': 'hr'})
hr_tags = list(hr_tags_cur)
hr_tags_num = hr_tags_cur.count()
print("{} Holding Registers".format(hr_tags_num))
return {'di': di_tags, 'co': co_tags, 'ir': ir_tags, 'hr': hr_tags}
# ---------------------------------------------------------------------------#
# create your custom data block with callbacks
# ---------------------------------------------------------------------------#
class DigitalTagDataBlock(ModbusSparseDataBlock):
''' A datablock that stores the new value in memory
and passes the operation to a message queue for further
processing.
'''
def __init__(self, register_type, tag_list):
'''
'''
values = {}
self.register_type = register_type
for t in tag_list:
try:
values[t['register_number']] = t['val']
except KeyError:
values[t['register_number']] = 911
# print("Initialized DigitalTagDataBlock for {} with values {}".format(self.register_type, values))
super(DigitalTagDataBlock, self).__init__(values)
def getValues(self, address, count=1):
client = MongoClient()
db = client.tag_data
tags = db.tag_vals
if count > 1:
for i in range(address, address + count):
tag_found = tags.find_one({'register_number': i, 'register_type': self.register_type})
print("{} = {}".format(tag_found['tag_name'], tag_found['val']))
super(DigitalTagDataBlock, self).setValues(address, tag_found['val'])
else:
tag_found = tags.find_one({'register_number': address, 'register_type': self.register_type})
print("{} = {}".format(tag_found['tag_name'], tag_found['val']))
super(DigitalTagDataBlock, self).setValues(address, tag_found['val'])
return super(DigitalTagDataBlock, self).getValues(address, count=count)
def setValues(self, address, value):
''' Sets the requested values of the datastore
:param address: The starting address
:param values: The new values to be set
'''
client = MongoClient()
db = client.tag_data
tags = db.tag_vals
tag_name = tags.find_one({'register_number': address, 'register_type': self.register_type})['tag_name']
plc.writeTag(PLC_IP_ADDRESS, tag_name, value)
class AnalogTagDataBlock(ModbusSparseDataBlock):
''' A datablock that stores the new value in memory
and passes the operation to a message queue for further
processing.
'''
def __init__(self, register_type, tag_list):
'''
'''
values = {}
self.register_type = register_type
for t in tag_list:
try:
values[t['register_number']] = t['val']
values[t['register_number'] + 1] = t['scale_type']
values[t['register_number'] + 2] = t['scale_multiplier']
values[t['register_number'] + 3] = 0
except KeyError:
values[t['register_number']] = 911
values[t['register_number'] + 1] = 2
values[t['register_number'] + 2] = 0
values[t['register_number'] + 3] = 0
values[t['register_number'] + 4] = 123
# print("Initialized AnalogTagDataBlock for {} with values {}".format(self.register_type, values))
super(AnalogTagDataBlock, self).__init__(values)
def getValues(self, address, count=1):
client = MongoClient()
db = client.tag_data
tags = db.tag_vals
if count > 1:
for i in range(address, address + count):
tag_found = tags.find_one({'register_number': i, 'register_type': self.register_type})
if tag_found:
print("{} = {}".format(tag_found['tag_name'], tag_found['val']))
super(AnalogTagDataBlock, self).setValues(address, tag_found['val'])
super(AnalogTagDataBlock, self).setValues(address + 3, 0)
else:
tag_found = tags.find_one({'register_number': address, 'register_type': self.register_type})
if tag_found:
print("{} = {}".format(tag_found['tag_name'], tag_found['val']))
super(AnalogTagDataBlock, self).setValues(address, tag_found['val'])
super(AnalogTagDataBlock, self).setValues(address + 3, 0)
return super(AnalogTagDataBlock, self).getValues(address, count=count)
def setValues(self, address, value):
''' Sets the requested values of the datastore
:param address: The starting address
:param values: The new values to be set
'''
client = MongoClient()
db = client.tag_data
tags = db.tag_vals
tag_name = tags.find_one({'register_number': address, 'register_type': self.register_type})['tag_name']
plc.writeTag(PLC_IP_ADDRESS, tag_name, value)
def main():
# ---------------------------------------------------------------------------#
# initialize your data store
# ---------------------------------------------------------------------------#
tags_in_db = getTagsFromDB()
di_block = DigitalTagDataBlock('di', tags_in_db['di'])
co_block = DigitalTagDataBlock('co', tags_in_db['co'])
hr_block = AnalogTagDataBlock('hr', tags_in_db['hr'])
ir_block = AnalogTagDataBlock('ir', tags_in_db['ir'])
store = ModbusSlaveContext(di=di_block, co=co_block, hr=hr_block, ir=ir_block)
context = ModbusServerContext(slaves=store, single=True)
# ---------------------------------------------------------------------------#
# initialize the server information
# ---------------------------------------------------------------------------#
identity = ModbusDeviceIdentification()
identity.VendorName = 'pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'
# ---------------------------------------------------------------------------#
# run the server you want
# ---------------------------------------------------------------------------#
StartTcpServer(context, identity=identity, address=("localhost", 5020))
if __name__ == '__main__':
main()

79
test.py Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env python
'''
Pymodbus Synchronous Client Examples
--------------------------------------------------------------------------
The following is an example of how to use the synchronous modbus client
implementation from pymodbus.
It should be noted that the client can also be used with
the guard construct that is available in python 2.5 and up::
with ModbusClient('127.0.0.1') as client:
result = client.read_coils(1,10)
print result
'''
# ---------------------------------------------------------------------------#
# import the various server implementations
# ---------------------------------------------------------------------------#
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
# from pymodbus.client.sync import ModbusUdpClient as ModbusClient
# from pymodbus.client.sync import ModbusSerialClient as ModbusClient
# ---------------------------------------------------------------------------#
# configure the client logging
# ---------------------------------------------------------------------------#
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.INFO)
# ---------------------------------------------------------------------------#
# choose the client you want
# ---------------------------------------------------------------------------#
# make sure to start an implementation to hit against. For this
# you can use an existing device, the reference implementation in the tools
# directory, or start a pymodbus server.
#
# If you use the UDP or TCP clients, you can override the framer being used
# to use a custom implementation (say RTU over TCP). By default they use the
# socket framer::
#
# client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer)
#
# It should be noted that you can supply an ipv4 or an ipv6 host address for
# both the UDP and TCP clients.
#
# There are also other options that can be set on the client that controls
# how transactions are performed. The current ones are:
#
# * retries - Specify how many retries to allow per transaction (default = 3)
# * retry_on_empty - Is an empty response a retry (default = False)
# * source_address - Specifies the TCP source address to bind to
#
# Here is an example of using these options::
#
# client = ModbusClient('localhost', retries=3, retry_on_empty=True)
# ---------------------------------------------------------------------------#
client = ModbusClient('localhost', port=5020)
# client = ModbusClient(method='ascii', port='/dev/pts/2', timeout=1)
# client = ModbusClient(method='rtu', port='/dev/pts/2', timeout=1)
client.connect()
# ---------------------------------------------------------------------------#
# specify slave to query
# ---------------------------------------------------------------------------#
# The slave to query is specified in an optional parameter for each
# individual request. This can be done by specifying the `unit` parameter
# which defaults to `0x00`
# ---------------------------------------------------------------------------#
print("HOLDING REGISTERS")
for i in range(0, 21):
rd = client.read_holding_registers(i * 5, 5)
print rd.registers
print("INPUT REGISTERS")
for i in range(2, 125):
rd = client.read_input_registers(i * 5, 5)
print rd.registers
# ---------------------------------------------------------------------------#
# close the client
# ---------------------------------------------------------------------------#
client.close()