ソースを参照

h803x: Initial implementation

This module implements support for the Veris H8035 and H8036 Energy
Meters.

The H8036 is similar to the H8035, but provides much more data.

The Enercept H8035/H8036 is an innovative three-phase networked
(Modbus RTU) power transducer that combines electronics and high
accuracy industrial grade CTs in a single package. The need for
external electrical enclosures is eliminated, greatly reducing
installation time and cost. Color-coordination between voltage leads
and CTs makes phase matching easy. Additionally, these transducers
automatically detect and compensate for phase reversal, eliminating
the concern of CT load orientation. Up to 63 Transducers can be
daisy-chained on a single RS-485 network.

This module was developed using libmodbus 3.1.2, and the H8035.  The
H8036 has not been tested.  libmodbus 3.1.2 must be present for this
module to build.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Abhishek Malik <abhishek.malik@intel.com>
Jon Trulson 9 年 前
コミット
5a5637a431

+ 1
- 0
examples/c++/CMakeLists.txt ファイルの表示

@@ -234,6 +234,7 @@ if (MODBUS_FOUND)
234 234
   include_directories(${MODBUS_INCLUDE_DIRS})
235 235
   add_example (t3311)
236 236
   add_example (hwxpxx)
237
+  add_example (h803x)
237 238
 endif()
238 239
 add_example (hdxxvxta)
239 240
 add_example (rhusb)

+ 149
- 0
examples/c++/h803x.cxx ファイルの表示

@@ -0,0 +1,149 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <iostream>
27
+#include <signal.h>
28
+
29
+#include "h803x.h"
30
+
31
+using namespace std;
32
+
33
+bool shouldRun = true;
34
+
35
+void sig_handler(int signo)
36
+{
37
+  if (signo == SIGINT)
38
+    shouldRun = false;
39
+}
40
+
41
+int main(int argc, char **argv)
42
+{
43
+  signal(SIGINT, sig_handler);
44
+
45
+//! [Interesting]
46
+
47
+  string defaultDev = "/dev/ttyUSB0";
48
+
49
+  // if an argument was specified, use it as the device instead
50
+  if (argc > 1)
51
+    defaultDev = string(argv[1]);
52
+
53
+  cout << "Using device " << defaultDev << endl;
54
+  cout << "Initializing..." << endl;
55
+
56
+  // Instantiate an H803X instance, using MODBUS slave address 1, and
57
+  // default comm parameters (9600, 8, N, 2)
58
+  upm::H803X *sensor = new upm::H803X(defaultDev, 1);
59
+
60
+  // output the Slave ID string
61
+  cout << "Slave ID: " << sensor->getSlaveID() << endl;
62
+  cout << endl;
63
+
64
+  // update and print available values every second
65
+  while (shouldRun)
66
+    {
67
+      // update our values from the sensor
68
+      sensor->update();
69
+
70
+      // H8035 / H8036
71
+      cout << "Consumption (kWh): " << sensor->getConsumption() << endl;
72
+      cout << "Real Power (kW): " << sensor->getRealPower() << endl;
73
+
74
+      if (sensor->isH8036())
75
+        {
76
+          // The H8036 has much more data available...
77
+
78
+          cout << "Reactive Power (kVAR): " << sensor->getReactivePower() 
79
+               << endl;
80
+          cout << "Apparent Power (kVA): " << sensor->getApparentPower() 
81
+               << endl;
82
+          cout << "Power Factor: " << sensor->getPowerFactor() 
83
+               << endl;
84
+          cout << "Volts Line to Line: " << sensor->getVoltsLineToLine() 
85
+               << endl;
86
+          cout << "Volts Line to Neutral: " << sensor->getVoltsLineToNeutral() 
87
+               << endl;
88
+
89
+          cout << "Current: " << sensor->getCurrent() 
90
+               << endl;
91
+
92
+          cout << "Real Power Phase A (kW): " << sensor->getRealPowerPhaseA() 
93
+               << endl;
94
+          cout << "Real Power Phase B (kW): " << sensor->getRealPowerPhaseB() 
95
+               << endl;
96
+          cout << "Real Power Phase C (kW): " << sensor->getRealPowerPhaseC() 
97
+               << endl;
98
+
99
+          cout << "Power Factor Phase A: " << sensor->getPowerFactorPhaseA() 
100
+               << endl;
101
+          cout << "Power Factor Phase B: " << sensor->getPowerFactorPhaseB() 
102
+               << endl;
103
+          cout << "Power Factor Phase C: " << sensor->getPowerFactorPhaseC() 
104
+               << endl;
105
+
106
+          cout << "Volts Phase A to B: " << sensor->getVoltsPhaseAToB() 
107
+               << endl;
108
+          cout << "Volts Phase B to C: " << sensor->getVoltsPhaseBToC() 
109
+               << endl;
110
+          cout << "Volts Phase A to C: " << sensor->getVoltsPhaseAToC() 
111
+               << endl;
112
+          cout << "Volts Phase A to Neutral: "
113
+               << sensor->getVoltsPhaseAToNeutral() 
114
+               << endl;
115
+          cout << "Volts Phase B to Neutral: "
116
+               << sensor->getVoltsPhaseBToNeutral() 
117
+               << endl;
118
+          cout << "Volts Phase C to Neutral: "
119
+               << sensor->getVoltsPhaseCToNeutral() 
120
+               << endl;
121
+
122
+          cout << "Current Phase A: " << sensor->getCurrentPhaseA() 
123
+               << endl;
124
+          cout << "Current Phase B: " << sensor->getCurrentPhaseB() 
125
+               << endl;
126
+          cout << "Current Phase C: " << sensor->getCurrentPhaseC() 
127
+               << endl;
128
+
129
+          cout << "Avg Real Power (kW): " << sensor->getAvgRealPower() 
130
+               << endl;
131
+          cout << "Min Real Power (kW): " << sensor->getMinRealPower() 
132
+               << endl;
133
+          cout << "Max Real Power (kW): " << sensor->getMaxRealPower() 
134
+               << endl;
135
+        }
136
+
137
+      cout << endl;
138
+
139
+      sleep(2);
140
+    }
141
+
142
+  cout << "Exiting..." << endl;
143
+
144
+  delete sensor;
145
+
146
+//! [Interesting]
147
+
148
+  return 0;
149
+}

+ 3
- 0
examples/java/CMakeLists.txt ファイルの表示

@@ -110,6 +110,9 @@ add_example(TEAMS_Example teams)
110 110
 add_example(APA102Sample apa102)
111 111
 add_example(TEX00_Example tex00)
112 112
 add_example(BMI160_Example bmi160)
113
+if (MODBUS_FOUND)
114
+  add_example(H803X_Example h803x)
115
+endif()
113 116
 
114 117
 add_example_with_path(Jhd1313m1_lcdSample lcd/upm_i2clcd.jar)
115 118
 add_example_with_path(Jhd1313m1Sample lcd/upm_i2clcd.jar)

+ 123
- 0
examples/java/H803X_Example.java ファイルの表示

@@ -0,0 +1,123 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+import upm_h803x.H803X;
26
+
27
+public class H803X_Example 
28
+{
29
+    private static String defaultDev = "/dev/ttyUSB0";
30
+
31
+    public static void main(String[] args) throws InterruptedException
32
+    {
33
+// ! [Interesting]
34
+        if (args.length > 0)
35
+            defaultDev = args[0];
36
+        System.out.println("Using device " + defaultDev);
37
+        System.out.println("Initializing...");
38
+
39
+        // Instantiate an H803X instance, using MODBUS slave address 1, and
40
+        // default comm parameters (9600, 8, N, 2)
41
+        H803X sensor = new H803X(defaultDev, 1);
42
+        
43
+        // output the Slave ID (manufacturer, model, serno)
44
+        System.out.println("Slave ID: " + sensor.getSlaveID());
45
+        System.out.println();
46
+
47
+        while (true)
48
+            {
49
+                // update our values from the sensor
50
+                sensor.update();
51
+
52
+                // H8035 / H8036
53
+                System.out.println("Consumption (kWh): " 
54
+                                   + sensor.getConsumption());
55
+                System.out.println("Real Power (kW): " 
56
+                                   + sensor.getRealPower());
57
+
58
+                if (sensor.isH8036())
59
+                    {
60
+                        // The H8036 has much more data available...
61
+                        
62
+                        System.out.println("Reactive Power (kVAR): "
63
+                                           + sensor.getReactivePower());
64
+                        System.out.println("Apparent Power (kVA): "
65
+                                           + sensor.getApparentPower());
66
+                        System.out.println("Power Factor: "
67
+                                           + sensor.getPowerFactor());
68
+                        System.out.println("Volts Line to Line: "
69
+                                           + sensor.getVoltsLineToLine());
70
+                        System.out.println("Volts Line to Neutral: "
71
+                                           + sensor.getVoltsLineToNeutral());
72
+                        
73
+                        System.out.println("Current: " + sensor.getCurrent());
74
+                        
75
+                        System.out.println("Real Power Phase A (kW): "
76
+                                           + sensor.getRealPowerPhaseA());
77
+                        System.out.println("Real Power Phase B (kW): "
78
+                                           + sensor.getRealPowerPhaseB());
79
+                        System.out.println("Real Power Phase C (kW): "
80
+                                           + sensor.getRealPowerPhaseC());
81
+                        
82
+                        System.out.println("Power Factor Phase A: "
83
+                                           + sensor.getPowerFactorPhaseA());
84
+                        System.out.println("Power Factor Phase B: "
85
+                                           + sensor.getPowerFactorPhaseB());
86
+                        System.out.println("Power Factor Phase C: "
87
+                                           + sensor.getPowerFactorPhaseC());
88
+                        
89
+                        System.out.println("Volts Phase A to B: "
90
+                                           + sensor.getVoltsPhaseAToB());
91
+                        System.out.println("Volts Phase B to C: "
92
+                                           + sensor.getVoltsPhaseBToC());
93
+                        System.out.println("Volts Phase A to C: "
94
+                                           + sensor.getVoltsPhaseAToC());
95
+                        System.out.println("Volts Phase A to Neutral: "
96
+                                           + sensor.getVoltsPhaseAToNeutral());
97
+                        System.out.println("Volts Phase B to Neutral: "
98
+                                           + sensor.getVoltsPhaseBToNeutral());
99
+                        System.out.println("Volts Phase C to Neutral: "
100
+                                           + sensor.getVoltsPhaseCToNeutral());
101
+                        
102
+                        System.out.println("Current Phase A: "
103
+                                           + sensor.getCurrentPhaseA());
104
+                        System.out.println("Current Phase B: "
105
+                                           + sensor.getCurrentPhaseB());
106
+                        System.out.println("Current Phase C: "
107
+                                           + sensor.getCurrentPhaseC());
108
+                        
109
+                        System.out.println("Avg Real Power (kW): "
110
+                                           + sensor.getAvgRealPower());
111
+                        System.out.println("Min Real Power (kW): "
112
+                                           + sensor.getMinRealPower());
113
+                        System.out.println("Max Real Power (kW): "
114
+                                           + sensor.getMaxRealPower());
115
+                    }
116
+
117
+                System.out.println();
118
+                Thread.sleep(2000);
119
+            }
120
+
121
+// ! [Interesting]
122
+    }
123
+}

+ 115
- 0
examples/javascript/h803x.js ファイルの表示

@@ -0,0 +1,115 @@
1
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
2
+/*jshint unused:true */
3
+
4
+/*
5
+ * Author: Jon Trulson <jtrulson@ics.com>
6
+ * Copyright (c) 2016 Intel Corporation.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining
9
+ * a copy of this software and associated documentation files (the
10
+ * "Software"), to deal in the Software without restriction, including
11
+ * without limitation the rights to use, copy, modify, merge, publish,
12
+ * distribute, sublicense, and/or sell copies of the Software, and to
13
+ * permit persons to whom the Software is furnished to do so, subject to
14
+ * the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+
29
+var sensorObj = require('jsupm_h803x');
30
+
31
+
32
+/************** Main code **************/
33
+
34
+var defaultDev = "/dev/ttyUSB0";
35
+
36
+// if an argument was specified, use it as the device instead
37
+if (process.argv.length > 2)
38
+{
39
+    defaultDev = process.argv[2];
40
+}
41
+
42
+console.log("Using device " + defaultDev);
43
+console.log("Initializing...");
44
+
45
+// Instantiate an H803X instance, using MODBUS slave address 1, and
46
+// default comm parameters (9600, 8, N, 2)
47
+var sensor = new sensorObj.H803X(defaultDev, 1);
48
+
49
+// output the Slave ID (manufacturer, model, serno)
50
+console.log("Slave ID:", sensor.getSlaveID());
51
+
52
+console.log("");
53
+
54
+// update and print available values every second
55
+setInterval(function()
56
+{
57
+    // update our values from the sensor
58
+    sensor.update();
59
+
60
+    // H8035 / H8036
61
+    console.log("Consumption (kWh):", sensor.getConsumption());
62
+    console.log("Real Power (kW):", sensor.getRealPower());
63
+
64
+    if (sensor.isH8036())
65
+    {
66
+        // The H8036 has much more data available...
67
+
68
+          console.log("Reactive Power (kVAR):", sensor.getReactivePower());
69
+          console.log("Apparent Power (kVA):", sensor.getApparentPower());
70
+          console.log("Power Factor:", sensor.getPowerFactor());
71
+          console.log("Volts Line to Line:", sensor.getVoltsLineToLine());
72
+          console.log("Volts Line to Neutral:", sensor.getVoltsLineToNeutral());
73
+
74
+          console.log("Current:", sensor.getCurrent());
75
+
76
+          console.log("Real Power Phase A (kW):", sensor.getRealPowerPhaseA());
77
+          console.log("Real Power Phase B (kW):", sensor.getRealPowerPhaseB());
78
+          console.log("Real Power Phase C (kW):", sensor.getRealPowerPhaseC());
79
+
80
+          console.log("Power Factor Phase A:", sensor.getPowerFactorPhaseA());
81
+          console.log("Power Factor Phase B:", sensor.getPowerFactorPhaseB());
82
+          console.log("Power Factor Phase C:", sensor.getPowerFactorPhaseC());
83
+
84
+          console.log("Volts Phase A to B:", sensor.getVoltsPhaseAToB());
85
+          console.log("Volts Phase B to C:", sensor.getVoltsPhaseBToC());
86
+          console.log("Volts Phase A to C:", sensor.getVoltsPhaseAToC());
87
+          console.log("Volts Phase A to Neutral: ",
88
+                      sensor.getVoltsPhaseAToNeutral());
89
+          console.log("Volts Phase B to Neutral: ",
90
+                      sensor.getVoltsPhaseBToNeutral());
91
+          console.log("Volts Phase C to Neutral: ",
92
+                      sensor.getVoltsPhaseCToNeutral());
93
+
94
+          console.log("Current Phase A:", sensor.getCurrentPhaseA());
95
+          console.log("Current Phase B:", sensor.getCurrentPhaseB());
96
+          console.log("Current Phase C:", sensor.getCurrentPhaseC());
97
+
98
+          console.log("Avg Real Power (kW):", sensor.getAvgRealPower());
99
+          console.log("Min Real Power (kW):", sensor.getMinRealPower());
100
+          console.log("Max Real Power (kW):", sensor.getMaxRealPower());
101
+    }
102
+
103
+    console.log("");
104
+
105
+}, 2000);
106
+
107
+
108
+process.on('SIGINT', function()
109
+{
110
+    sensor = null;
111
+    sensorObj.cleanUp();
112
+    sensorObj = null;
113
+    console.log("Exiting...");
114
+    process.exit(0);
115
+});

+ 106
- 0
examples/python/h803x.py ファイルの表示

@@ -0,0 +1,106 @@
1
+#!/usr/bin/python
2
+# Author: Jon Trulson <jtrulson@ics.com>
3
+# Copyright (c) 2016 Intel Corporation.
4
+#
5
+# Permission is hereby granted, free of charge, to any person obtaining
6
+# a copy of this software and associated documentation files (the
7
+# "Software"), to deal in the Software without restriction, including
8
+# without limitation the rights to use, copy, modify, merge, publish,
9
+# distribute, sublicense, and/or sell copies of the Software, and to
10
+# permit persons to whom the Software is furnished to do so, subject to
11
+# the following conditions:
12
+#
13
+# The above copyright notice and this permission notice shall be
14
+# included in all copies or substantial portions of the Software.
15
+#
16
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+import time, sys, signal, atexit
25
+import pyupm_h803x as sensorObj
26
+
27
+## Exit handlers ##
28
+# This function stops python from printing a stacktrace when you hit control-C
29
+def SIGINTHandler(signum, frame):
30
+	raise SystemExit
31
+
32
+# This function lets you run code on exit
33
+def exitHandler():
34
+	print "Exiting..."
35
+	sys.exit(0)
36
+
37
+# Register exit handlers
38
+atexit.register(exitHandler)
39
+signal.signal(signal.SIGINT, SIGINTHandler)
40
+
41
+defaultDev = "/dev/ttyUSB0"
42
+
43
+# if an argument was specified, use it as the device instead
44
+if (len(sys.argv) > 1):
45
+        defaultDev = sys.argv[1]
46
+
47
+print "Using device", defaultDev
48
+print "Initializing..."
49
+
50
+# Instantiate an H803X instance, using MODBUS slave address 1, and
51
+# default comm parameters (9600, 8, N, 2)
52
+sensor = sensorObj.H803X(defaultDev, 1)
53
+
54
+# output the serial number and firmware revision
55
+print "Slave ID:", sensor.getSlaveID()
56
+
57
+print
58
+
59
+# update and print available values every second
60
+while (1):
61
+        # update our values from the sensor
62
+        sensor.update()
63
+
64
+        # H8035 / H8036
65
+        print "Consumption (kWh):", sensor.getConsumption()
66
+        print "Real Power (kW):", sensor.getRealPower()
67
+
68
+        if (sensor.isH8036()):
69
+                # The H8036 has much more data available...
70
+
71
+                print "Reactive Power (kVAR):", sensor.getReactivePower()
72
+                print "Apparent Power (kVA):", sensor.getApparentPower()
73
+                print "Power Factor:", sensor.getPowerFactor()
74
+                print "Volts Line to Line:", sensor.getVoltsLineToLine()
75
+                print "Volts Line to Neutral:", sensor.getVoltsLineToNeutral()
76
+
77
+                print "Current:", sensor.getCurrent()
78
+
79
+                print "Real Power Phase A (kW):", sensor.getRealPowerPhaseA()
80
+                print "Real Power Phase B (kW):", sensor.getRealPowerPhaseB()
81
+                print "Real Power Phase C (kW):", sensor.getRealPowerPhaseC()
82
+
83
+                print "Power Factor Phase A:", sensor.getPowerFactorPhaseA()
84
+                print "Power Factor Phase B:", sensor.getPowerFactorPhaseB()
85
+                print "Power Factor Phase C:", sensor.getPowerFactorPhaseC()
86
+
87
+                print "Volts Phase A to B:", sensor.getVoltsPhaseAToB()
88
+                print "Volts Phase B to C:", sensor.getVoltsPhaseBToC()
89
+                print "Volts Phase A to C:", sensor.getVoltsPhaseAToC()
90
+                print "Volts Phase A to Neutral: ",
91
+                print sensor.getVoltsPhaseAToNeutral()
92
+                print "Volts Phase B to Neutral: ",
93
+                print sensor.getVoltsPhaseBToNeutral()
94
+                print "Volts Phase C to Neutral: ",
95
+                print sensor.getVoltsPhaseCToNeutral()
96
+
97
+                print "Current Phase A:", sensor.getCurrentPhaseA()
98
+                print "Current Phase B:", sensor.getCurrentPhaseB()
99
+                print "Current Phase C:", sensor.getCurrentPhaseC()
100
+
101
+                print "Avg Real Power (kW):", sensor.getAvgRealPower()
102
+                print "Min Real Power (kW):", sensor.getMinRealPower()
103
+                print "Max Real Power (kW):", sensor.getMaxRealPower()
104
+
105
+        print
106
+	time.sleep(2)

+ 24
- 0
src/h803x/CMakeLists.txt ファイルの表示

@@ -0,0 +1,24 @@
1
+set (libname "h803x")
2
+set (libdescription "upm module for the Veris H803X (H8035/H8036)")
3
+set (module_src ${libname}.cxx)
4
+set (module_h ${libname}.h)
5
+
6
+pkg_search_module(MODBUS libmodbus)
7
+if (MODBUS_FOUND)
8
+  set (reqlibname "libmodbus")
9
+  include_directories(${MODBUS_INCLUDE_DIRS})
10
+  upm_module_init()
11
+  add_dependencies(${libname} ${MODBUS_LIBRARIES})
12
+  target_link_libraries(${libname} ${MODBUS_LIBRARIES})
13
+  if (BUILDSWIG)
14
+    if (BUILDSWIGNODE)
15
+      swig_link_libraries (jsupm_${libname} ${MODBUS_LIBRARIES} ${MRAA_LIBRARIES} ${NODE_LIBRARIES})
16
+    endif()
17
+    if (BUILDSWIGPYTHON)
18
+      swig_link_libraries (pyupm_${libname} ${MODBUS_LIBRARIES} ${PYTHON_LIBRARIES} ${MRAA_LIBRARIES})
19
+    endif()
20
+    if (BUILDSWIGJAVA)
21
+      swig_link_libraries (javaupm_${libname} ${MODBUS_LIBRARIES} ${MRAAJAVA_LDFLAGS} ${JAVA_LDFLAGS})
22
+    endif()
23
+  endif()
24
+endif ()

+ 356
- 0
src/h803x/h803x.cxx ファイルの表示

@@ -0,0 +1,356 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <assert.h>
27
+#include <errno.h>
28
+#include <iostream>
29
+#include <stdexcept>
30
+#include <string>
31
+
32
+#include "h803x.h"
33
+
34
+using namespace upm;
35
+using namespace std;
36
+
37
+// We can't use the modbus float conversion functions since they
38
+// assume the first word is the LSW.  On this device, the first word
39
+// is MSW.  In addition, the data is already IEEE 754 formatted, which
40
+// won't work with just the bit shuffling modbus_get_float*() does.
41
+static float regs2float(uint16_t h, uint16_t l)
42
+{
43
+  // this function will fail horribly if the following isn't true
44
+  assert(sizeof(float) == sizeof(uint32_t));
45
+
46
+  // we can't use a cast here, since the data is already IEEE 754
47
+  // formatted, so use a union instead.
48
+  union {
49
+    uint32_t i;
50
+    float f;
51
+  } converter;
52
+
53
+  converter.i = ((uint32_t)h << 16) | l;
54
+  return converter.f;
55
+}
56
+
57
+
58
+H803X::H803X(std::string device, int address, int baud, int bits, char parity,
59
+               int stopBits) :
60
+  m_mbContext(0)
61
+{
62
+  // check some of the parameters
63
+  if (!(bits == 7 || bits == 8))
64
+    {
65
+      throw std::out_of_range(std::string(__FUNCTION__)
66
+                              + ": bits must be 7 or 8");
67
+    }
68
+
69
+  if (!(parity == 'N' || parity == 'E' || parity == 'O'))
70
+    {
71
+      throw std::out_of_range(std::string(__FUNCTION__)
72
+                              + ": parity must be 'N', 'O', or 'E'");
73
+    }
74
+
75
+  if (!(stopBits == 1 || stopBits == 2))
76
+    {
77
+      throw std::out_of_range(std::string(__FUNCTION__)
78
+                              + ": stopBits must be 1 or 2");
79
+    }
80
+
81
+  // now, open/init the device and modbus context
82
+
83
+  if (!(m_mbContext = modbus_new_rtu(device.c_str(), baud, parity, bits,
84
+                                     stopBits)))
85
+    {
86
+      throw std::runtime_error(std::string(__FUNCTION__)
87
+                               + ": modbus_new_rtu() failed");
88
+    }
89
+
90
+  // set the slave address of the device we want to talk to
91
+
92
+  // addresses are only 8bits wide
93
+  address &= 0xff;
94
+  if (modbus_set_slave(m_mbContext, address))
95
+    {
96
+      throw std::runtime_error(std::string(__FUNCTION__)
97
+                               + ": modbus_set_slave() failed");
98
+    }
99
+
100
+  // set the serial mode
101
+  modbus_rtu_set_serial_mode(m_mbContext, MODBUS_RTU_RS232);
102
+
103
+  // now connect..
104
+  if (modbus_connect(m_mbContext))
105
+    {
106
+      throw std::runtime_error(std::string(__FUNCTION__)
107
+                               + ": modbus_connect() failed");
108
+    }
109
+
110
+  // will set m_isH8036 appropriately
111
+  testH8036();
112
+
113
+  clearData();
114
+
115
+  // turn off debugging
116
+  setDebug(false);
117
+}
118
+
119
+H803X::~H803X()
120
+{
121
+  if (m_mbContext)
122
+    {
123
+      modbus_close(m_mbContext);
124
+      modbus_free(m_mbContext);
125
+    }
126
+}
127
+
128
+int H803X::readHoldingRegs(HOLDING_REGS_T reg, int len, uint16_t *buf)
129
+{
130
+  int rv;
131
+  int retries = 5;
132
+
133
+  // Sometimes it seems the device goes to sleep, and therefore a read
134
+  // will timeout, so we will retry up to 5 times.
135
+
136
+  while (retries >= 0)
137
+    {
138
+      if ((rv = modbus_read_registers(m_mbContext, reg, len, buf)) < 0)
139
+        {
140
+          if (errno == ETIMEDOUT)
141
+            {
142
+              // timeout
143
+              retries--;
144
+              sleep(1);
145
+            }
146
+          else if (errno == EMBXILADD)
147
+            {
148
+              // invalid registers will return a EMBXILADD (modbus)
149
+              // error.  We want to detect these as a way to determine
150
+              // whether we are dealing with an H8035 or H8036.
151
+              return -1;
152
+            }
153
+          else
154
+            {
155
+              // anything else is a failure.
156
+              throw std::runtime_error(std::string(__FUNCTION__)
157
+                                       + ": modbus_read_registers() failed: "
158
+                                       + modbus_strerror(errno));
159
+            }
160
+        }
161
+      else
162
+        return rv;              // success
163
+    }
164
+
165
+  // if we're here, then all the retries were exhausted
166
+  throw std::runtime_error(std::string(__FUNCTION__)
167
+                           + ": modbus_read_registers() timed out after "
168
+                           + "5 retries");
169
+}
170
+
171
+void H803X::writeHoldingReg(HOLDING_REGS_T reg, int value)
172
+{
173
+  if (modbus_write_register(m_mbContext, reg, value) != 1)
174
+    {
175
+      throw std::runtime_error(std::string(__FUNCTION__)
176
+                               + ": modbus_write_register() failed: "
177
+                               + modbus_strerror(errno));
178
+    }
179
+}
180
+
181
+void H803X::update()
182
+{
183
+  static const int h8035NumRegs = 4; // 2 regs * 2
184
+  static const int h8036NumRegs = 52; // 26 regs * 2
185
+
186
+  int numRegs = (isH8036() ? h8036NumRegs : h8035NumRegs);
187
+
188
+  uint16_t buf[numRegs];
189
+
190
+  // This should only fail (return -1) if we got isH8036() wrong
191
+  if (readHoldingRegs(HOLDING_CONSUMPTION_KWH, numRegs, buf) < 0)
192
+    {
193
+      throw std::out_of_range(std::string(__FUNCTION__) +
194
+                              ": readHoldingRegs() failed: "
195
+                               + modbus_strerror(errno));
196
+    }
197
+
198
+  // And so it begins...
199
+
200
+  // H8035 / H8036
201
+  m_consumptionkWh              = regs2float(buf[0], buf[1]);
202
+  m_realPowerkW                 = regs2float(buf[2], buf[3]);
203
+  
204
+  // H8036 only
205
+  if (isH8036())
206
+    {
207
+      m_reactivePowerkVAR       = regs2float(buf[4], buf[5]);
208
+      m_apparentPowerkVA        = regs2float(buf[6], buf[7]);
209
+      m_powerFactor             = regs2float(buf[8], buf[9]);
210
+      
211
+      m_voltsLineToLine         = regs2float(buf[10], buf[11]);
212
+      m_voltsLineToNeutral      = regs2float(buf[12], buf[13]);
213
+      
214
+      m_current                 = regs2float(buf[14], buf[15]);
215
+      
216
+      m_realPowerPhaseAkW       = regs2float(buf[16], buf[17]);
217
+      m_realPowerPhaseBkW       = regs2float(buf[18], buf[19]);
218
+      m_realPowerPhaseCkW       = regs2float(buf[20], buf[21]);
219
+      
220
+      m_powerFactorPhaseA       = regs2float(buf[22], buf[23]);
221
+      m_powerFactorPhaseB       = regs2float(buf[24], buf[25]);
222
+      m_powerFactorPhaseC       = regs2float(buf[26], buf[27]);
223
+      
224
+      m_voltsPhaseAB            = regs2float(buf[28], buf[29]);
225
+      m_voltsPhaseBC            = regs2float(buf[30], buf[31]);
226
+      m_voltsPhaseAC            = regs2float(buf[32], buf[33]);
227
+      m_voltsPhaseAN            = regs2float(buf[34], buf[35]);
228
+      m_voltsPhaseBN            = regs2float(buf[36], buf[37]);
229
+      m_voltsPhaseCN            = regs2float(buf[38], buf[39]);
230
+      
231
+      m_currentPhaseA           = regs2float(buf[40], buf[41]);
232
+      m_currentPhaseB           = regs2float(buf[42], buf[43]);
233
+      m_currentPhaseC           = regs2float(buf[44], buf[45]);
234
+      
235
+      m_avgRealPowerkW          = regs2float(buf[46], buf[47]);
236
+      m_minRealPowerkW          = regs2float(buf[48], buf[49]);
237
+      m_maxRealPowerkW          = regs2float(buf[50], buf[51]);
238
+    }
239
+}
240
+
241
+string H803X::getSlaveID()
242
+{
243
+  uint8_t id[MODBUS_MAX_PDU_LENGTH];
244
+  int rv;
245
+
246
+  if ((rv = modbus_report_slave_id(m_mbContext, MODBUS_MAX_PDU_LENGTH, id)) < 0)
247
+    {
248
+      throw std::runtime_error(std::string(__FUNCTION__)
249
+                               + ": modbus_report_slave_id() failed: "
250
+                               + modbus_strerror(errno));
251
+
252
+    }
253
+
254
+  // the first byte is the number of bytes in the response, the second
255
+  // byte is the active indicator (00 = off, ff = on), and the rest
256
+  // are ascii identification (company, model, and serial number) data.
257
+
258
+  if (rv > 2)
259
+    {
260
+      string retID((char *)&id[2], rv - 2);
261
+      return retID;
262
+    }
263
+  else
264
+    return "";
265
+}
266
+
267
+void H803X::setSlaveAddress(int addr)
268
+{
269
+  // addresses are only 8bits wide
270
+  addr &= 0xff;
271
+
272
+  if (modbus_set_slave(m_mbContext, addr))
273
+    {
274
+      throw std::runtime_error(std::string(__FUNCTION__)
275
+                               + ": modbus_set_slave() failed: "
276
+                               + modbus_strerror(errno));
277
+    }
278
+
279
+  // retest H8036
280
+  testH8036();
281
+
282
+  // clear out any previously stored data
283
+  clearData();
284
+}
285
+
286
+void H803X::setDebug(bool enable)
287
+{
288
+  m_debugging = enable;
289
+
290
+  if (enable)
291
+    modbus_set_debug(m_mbContext, 1);
292
+  else
293
+    modbus_set_debug(m_mbContext, 0);
294
+}
295
+
296
+void H803X::clearData()
297
+{
298
+    // H8035
299
+    m_consumptionkWh = 0.0;
300
+    m_realPowerkW = 0.0;
301
+
302
+    // H8036
303
+    m_reactivePowerkVAR = 0.0;
304
+    m_apparentPowerkVA = 0.0;
305
+    m_powerFactor = 0.0;
306
+    m_voltsLineToLine = 0.0;
307
+    m_voltsLineToNeutral = 0.0;
308
+    m_current = 0.0;
309
+    m_realPowerPhaseAkW = 0.0;
310
+    m_realPowerPhaseBkW = 0.0;
311
+    m_realPowerPhaseCkW = 0.0;
312
+    m_powerFactorPhaseA = 0.0;
313
+    m_powerFactorPhaseB = 0.0;
314
+    m_powerFactorPhaseC = 0.0;
315
+    m_voltsPhaseAB = 0.0;
316
+    m_voltsPhaseBC = 0.0;
317
+    m_voltsPhaseAC = 0.0;
318
+    m_voltsPhaseAN = 0.0;
319
+    m_voltsPhaseBN = 0.0;
320
+    m_voltsPhaseCN = 0.0;
321
+    m_currentPhaseA = 0.0;
322
+    m_currentPhaseB = 0.0;
323
+    m_currentPhaseC = 0.0;
324
+    m_avgRealPowerkW = 0.0;
325
+    m_minRealPowerkW = 0.0;
326
+    m_maxRealPowerkW = 0.0;
327
+}
328
+
329
+void H803X::testH8036()
330
+{
331
+  // here we test a register read to see if we are on an H8036 device,
332
+  // which can provide much more information.
333
+
334
+  uint16_t regs[2];
335
+
336
+  // here, we'll read 2 registers that only exist on the H8036.  Any
337
+  // failure other than a illegal data access will generate an
338
+  // exception.  A valid request will return >0, and an illegal
339
+  // register read will return -1.
340
+  if (readHoldingRegs(HOLDING_REACTIVE_POWER_KVAR, 2, regs) == -1)
341
+    m_isH8036 = false;
342
+  else
343
+    m_isH8036 = true;
344
+}
345
+
346
+void H803X::presetConsumption(float value, MULTIPLIERS_T multiplier)
347
+{
348
+  uint32_t i = uint32_t(value * float(multiplier));
349
+
350
+  uint16_t h = uint16_t(i >> 16);
351
+  uint16_t l = uint16_t(i & 0xffff);
352
+
353
+  // always write the LSW first
354
+  writeHoldingReg(HOLDING_CONSUMPTION_KWH_INT_L, l);
355
+  writeHoldingReg(HOLDING_CONSUMPTION_KWH_INT_H, h);
356
+}

+ 547
- 0
src/h803x/h803x.h ファイルの表示

@@ -0,0 +1,547 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2016 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+#pragma once
25
+
26
+#include <string>
27
+
28
+#include <modbus/modbus.h>
29
+
30
+namespace upm {
31
+
32
+  /**
33
+   * @brief H803X Energy Meter
34
+   * @defgroup h803x libupm-h803x
35
+   * @ingroup uart electric
36
+   */
37
+
38
+  /**
39
+   * @library h803x
40
+   * @sensor h803x
41
+   * @comname UPM API for the Veris H803X Energy Meter
42
+   * @type electic
43
+   * @man veris
44
+   * @con uart
45
+   * @web http://www.veris.com/Item/H8035-0100-2.aspx
46
+   *
47
+   * @brief UPM API for the Veris H803X Energy Meter
48
+   *
49
+   * This module implements support for the Veris H8035 and H8036
50
+   * Energy Meters.
51
+   *
52
+   * The H8036 is similar to the H8035, but provides much more data.
53
+   *
54
+   * The Enercept H8035/H8036 is an innovative three-phase networked
55
+   * (Modbus RTU) power transducer that combines electronics and high
56
+   * accuracy industrial grade CTs in a single package. The need for
57
+   * external electrical enclosures is eliminated, greatly reducing
58
+   * installation time and cost. Color-coordination between voltage
59
+   * leads and CTs makes phase matching easy. Additionally, these
60
+   * transducers automatically detect and compensate for phase
61
+   * reversal, eliminating the concern of CT load orientation. Up to
62
+   * 63 Transducers can be daisy-chained on a single RS-485 network.
63
+   *
64
+   * This module was developed using libmodbus 3.1.2, and the H8035.
65
+   * The H8036 has not been tested.  libmodbus 3.1.2 must be present
66
+   * for this module to build.
67
+   *
68
+   * It was developed using an RS232->RS485 interface.  You cannot use
69
+   * the built in MCU TTL UART pins for accessing this device -- you
70
+   * must use a full Serial RS232->RS485 or USB-RS485 interface
71
+   * connected via USB.
72
+   *
73
+   * @snippet h803x.cxx Interesting
74
+   */
75
+
76
+  class H803X {
77
+  public:
78
+
79
+    // MODBUS holding registers.  These offsets are for the MSW only.
80
+    // The LSW always follows, though they are not enumerated here.
81
+    // These are all 2 register (32-bit total (16b HSW + 16b LSW))
82
+    // quantities, in IEEE 754 floating point format.
83
+    typedef enum {
84
+      // these two registers are used only for presetConsumption()
85
+      HOLDING_CONSUMPTION_KWH_INT_L             = 0, // preset use only
86
+      HOLDING_CONSUMPTION_KWH_INT_H             = 1, // preset use only
87
+
88
+      // H8035/H8036
89
+      HOLDING_CONSUMPTION_KWH                   = 258, // floating point data
90
+
91
+      HOLDING_REAL_POWER_KW                     = 260,
92
+
93
+      // H8036 only
94
+      HOLDING_REACTIVE_POWER_KVAR               = 262,
95
+      HOLDING_APPARENT_POWER_KVA                = 264,
96
+      HOLDING_POWER_FACTOR                      = 266,
97
+      HOLDING_VOLTS_LINE_TO_LINE                = 268,
98
+      HOLDING_VOLTS_LINE_TO_NEUTRAL             = 270,
99
+      HOLDING_CURRENT                           = 272,
100
+      HOLDING_REAL_POWER_PHASE_A_KWH            = 274,
101
+      HOLDING_REAL_POWER_PHASE_B_KWH            = 276,
102
+      HOLDING_REAL_POWER_PHASE_C_KWH            = 278,
103
+      HOLDING_POWER_FACTOR_PHASE_A              = 280,
104
+      HOLDING_POWER_FACTOR_PHASE_B              = 282,
105
+      HOLDING_POWER_FACTOR_PHASE_C              = 284,
106
+      HOLDING_VOLTS_PHASE_AB                    = 286,
107
+      HOLDING_VOLTS_PHASE_BC                    = 288,
108
+      HOLDING_VOLTS_PHASE_AC                    = 290,
109
+      HOLDING_VOLTS_PHASE_AN                    = 292,
110
+      HOLDING_VOLTS_PHASE_BN                    = 294,
111
+      HOLDING_VOLTS_PHASE_CN                    = 296,
112
+      HOLDING_CURRENT_PHASE_A                   = 298,
113
+      HOLDING_CURRENT_PHASE_B                   = 300,
114
+      HOLDING_CURRENT_PHASE_C                   = 302,
115
+      HOLDING_AVG_REAL_POWER_KW                 = 304,
116
+      HOLDING_MIN_REAL_POWER_KW                 = 306,
117
+      HOLDING_MAX_REAL_POWER_KW                 = 308
118
+    } HOLDING_REGS_T;
119
+
120
+    // these enums are used by presetConsumption() to scale the value
121
+    // properly depending on the devices' current capacity.
122
+    typedef enum {
123
+      MULT_100A                                 = 128, // 100A devices
124
+      MULT_300A_400A                            = 32,
125
+      MULT_800A                                 = 16,
126
+      MULT_1600A                                = 8,
127
+      MULT_2400A                                = 4
128
+    } MULTIPLIERS_T;
129
+
130
+    /**
131
+     * H803X constructor
132
+     *
133
+     * @param device Path to the serial device
134
+     * @param address The MODBUS slave address
135
+     * @param baud The baudrate of the device.  Default: 9600
136
+     * @param bits The number of bits per byte.  Default: 8
137
+     * @param parity The parity of the connection, 'N' for None, 'E'
138
+     * for Even, 'O' for Odd.  Default: 'N'
139
+     * @param stopBits The number of stop bits.  Default: 2
140
+     */
141
+    H803X(std::string device, int address, int baud=9600, int bits=8,
142
+          char parity='N', int stopBits=2);
143
+
144
+    /**
145
+     * H803X Destructor
146
+     */
147
+    ~H803X();
148
+
149
+    /**
150
+     * Read current values from the sensor and update internal stored
151
+     * values.  This method must be called prior to querying any
152
+     * values.
153
+     */
154
+    void update();
155
+
156
+    /**
157
+     * Return a string corresponding the the device's MODBUS slave ID.
158
+     *
159
+     * @return string represnting the MODBUS slave ID
160
+     */
161
+    std::string getSlaveID();
162
+
163
+    /**
164
+     * Set a new MODBUS slave address.  This is useful if you have
165
+     * multiple H803X devices on a single bus.  When this method is
166
+     * called, the current stored data is cleared, and a new attempt
167
+     * is made to determine whether the target device is an H8035 or
168
+     * H8036.
169
+     *
170
+     * @param addr The new slave address to set
171
+     */
172
+    void setSlaveAddress(int addr);
173
+
174
+    /**
175
+     * Preset the kWh accumulated Consumption registers to a
176
+     * predefined value.  This is generally not advised, but is
177
+     * provided for those installations that might require it.  The
178
+     * multiplier depends on the current range of your device.  Be
179
+     * sure to select the right multiplier for your devices'
180
+     * supported current capacity.
181
+     *
182
+     * @param value The desired value for the consumption accumulator
183
+     * registers in kWh.
184
+     * @param multiplier The correct MULTIPLIERS_T value for your device.
185
+     */
186
+    void presetConsumption(float value, MULTIPLIERS_T multiplier);
187
+
188
+    /**
189
+     * Return the accumulated consumption value, in kWh. update() must
190
+     * have been called prior to calling this method.
191
+     *
192
+     * @return The accumulated consumption.
193
+     */
194
+    float getConsumption()
195
+    {
196
+      return m_consumptionkWh;
197
+    };
198
+
199
+    /**
200
+     * Return the real power value in kW. update() must have been
201
+     * called prior to calling this method.
202
+     *
203
+     * @return The real power value in kW.
204
+     */
205
+    float getRealPower()
206
+    {
207
+      return m_realPowerkW;
208
+    };
209
+
210
+    /**
211
+     * Return the reactive power value in kVAR (kilo-volt Amperes
212
+     * Reactive). update() must have been called prior to calling this
213
+     * method.
214
+     *
215
+     * @return The reactive power value in kVAR.
216
+     */
217
+    float getReactivePower()
218
+    {
219
+      return m_reactivePowerkVAR;
220
+    };
221
+
222
+    /**
223
+     * Return the apparent power value in kVA. update() must have been
224
+     * called prior to calling this method.
225
+     *
226
+     * @return The apparent power value in kVA.
227
+     */
228
+    float getApparentPower()
229
+    {
230
+      return m_apparentPowerkVA;
231
+    };
232
+
233
+    /**
234
+     * Return the power factor value. update() must have been called
235
+     * prior to calling this method.
236
+     *
237
+     * @return The power factor.
238
+     */
239
+    float getPowerFactor()
240
+    {
241
+      return m_powerFactor;
242
+    };
243
+
244
+    /**
245
+     * Return the voltage line to line value. update() must have been
246
+     * called prior to calling this method.
247
+     *
248
+     * @return The voltage, line to line.
249
+     */
250
+    float getVoltsLineToLine()
251
+    {
252
+      return m_voltsLineToLine;
253
+    };
254
+
255
+    /**
256
+     * Return the voltage line to neutral. update() must have been
257
+     * called prior to calling this method.
258
+     *
259
+     * @return The voltage, line to neutral.
260
+     */
261
+    float getVoltsLineToNeutral()
262
+    {
263
+      return m_voltsLineToNeutral;
264
+    };
265
+
266
+    /**
267
+     * Return the current value in amps. update() must have been
268
+     * called prior to calling this method.
269
+     *
270
+     * @return The current value in amps.
271
+     */
272
+    float getCurrent()
273
+    {
274
+      return m_current;
275
+    };
276
+
277
+    /**
278
+     * Return the real power for phase A. update() must have been
279
+     * called prior to calling this method.
280
+     *
281
+     * @return The real power for phase A.
282
+     */
283
+    float getRealPowerPhaseA()
284
+    {
285
+      return m_realPowerPhaseAkW;
286
+    };
287
+
288
+    /**
289
+     * Return the real power for phase B. update() must have been
290
+     * called prior to calling this method.
291
+     *
292
+     * @return The real power for phase B.
293
+     */
294
+    float getRealPowerPhaseB()
295
+    {
296
+      return m_realPowerPhaseBkW;
297
+    };
298
+
299
+    /**
300
+     * Return the real power for phase C. update() must have been
301
+     * called prior to calling this method.
302
+     *
303
+     * @return The real power for phase C.
304
+     */
305
+    float getRealPowerPhaseC()
306
+    {
307
+      return m_realPowerPhaseCkW;
308
+    };
309
+
310
+    /**
311
+     * Return the power factor for phase A. update() must have been
312
+     * called prior to calling this method.
313
+     *
314
+     * @return The power factor for phase A.
315
+     */
316
+    float getPowerFactorPhaseA()
317
+    {
318
+      return m_powerFactorPhaseA;
319
+    };
320
+
321
+    /**
322
+     * Return the power factor for phase B. update() must have been
323
+     * called prior to calling this method.
324
+     *
325
+     * @return The power factor for phase B.
326
+     */
327
+    float getPowerFactorPhaseB()
328
+    {
329
+      return m_powerFactorPhaseB;
330
+    };
331
+
332
+    /**
333
+     * Return the power factor for phase C. update() must have been
334
+     * called prior to calling this method.
335
+     *
336
+     * @return The power factor for phase C.
337
+     */
338
+    float getPowerFactorPhaseC()
339
+    {
340
+      return m_powerFactorPhaseC;
341
+    };
342
+
343
+    /**
344
+     * Return the voltage for phase A to B. update() must have been
345
+     * called prior to calling this method.
346
+     *
347
+     * @return The voltage for phase A to B.
348
+     */
349
+    float getVoltsPhaseAToB()
350
+    {
351
+      return m_voltsPhaseAB;
352
+    };
353
+
354
+    /**
355
+     * Return the voltage for phase B to C. update() must have been
356
+     * called prior to calling this method.
357
+     *
358
+     * @return The voltage for phase B to C.
359
+     */
360
+    float getVoltsPhaseBToC()
361
+    {
362
+      return m_voltsPhaseBC;
363
+    };
364
+
365
+    /**
366
+     * Return the voltage for phase A to B. update() must have been
367
+     * called prior to calling this method.
368
+     *
369
+     * @return The voltage for phase A to B.
370
+     */
371
+    float getVoltsPhaseAToC()
372
+    {
373
+      return m_voltsPhaseAC;
374
+    };
375
+
376
+    /**
377
+     * Return the voltage for phase A to neutral. update() must have
378
+     * been called prior to calling this method.
379
+     *
380
+     * @return The voltage for phase A to neutral.
381
+     */
382
+    float getVoltsPhaseAToNeutral()
383
+    {
384
+      return m_voltsPhaseAN;
385
+    };
386
+
387
+    /**
388
+     * Return the voltage for phase B to neutral. update() must have
389
+     * been called prior to calling this method.
390
+     *
391
+     * @return The voltage for phase B to neutral.
392
+     */
393
+    float getVoltsPhaseBToNeutral()
394
+    {
395
+      return m_voltsPhaseBN;
396
+    };
397
+
398
+    /**
399
+     * Return the voltage for phase C to neutral. update() must have
400
+     * been called prior to calling this method.
401
+     *
402
+     * @return The voltage for phase C to neutral.
403
+     */
404
+    float getVoltsPhaseCToNeutral()
405
+    {
406
+      return m_voltsPhaseCN;
407
+    };
408
+
409
+    /**
410
+     * Return the current for phase A. update() must have been called
411
+     * prior to calling this method.
412
+     *
413
+     * @return The current for phase A.
414
+     */
415
+    float getCurrentPhaseA()
416
+    {
417
+      return m_currentPhaseA;
418
+    };
419
+
420
+    /**
421
+     * Return the current for phase B. update() must have been called
422
+     * prior to calling this method.
423
+     *
424
+     * @return The current for phase B.
425
+     */
426
+    float getCurrentPhaseB()
427
+    {
428
+      return m_currentPhaseB;
429
+    };
430
+
431
+    /**
432
+     * Return the current for phase C. update() must have been called
433
+     * prior to calling this method.
434
+     *
435
+     * @return The current for phase C.
436
+     */
437
+    float getCurrentPhaseC()
438
+    {
439
+      return m_currentPhaseC;
440
+    };
441
+
442
+    /**
443
+     * Return the average real power. update() must have been called
444
+     * prior to calling this method.
445
+     *
446
+     * @return The average real power.
447
+     */
448
+    float getAvgRealPower()
449
+    {
450
+      return m_avgRealPowerkW;
451
+    };
452
+
453
+    /**
454
+     * Return the minimum real power. update() must have been called
455
+     * prior to calling this method.
456
+     *
457
+     * @return The minimum real power.
458
+     */
459
+    float getMinRealPower()
460
+    {
461
+      return m_minRealPowerkW;
462
+    };
463
+
464
+    /**
465
+     * Return the maximum real power. update() must have been called
466
+     * prior to calling this method.
467
+     *
468
+     * @return The maximum real power.
469
+     */
470
+    float getMaxRealPower()
471
+    {
472
+      return m_maxRealPowerkW;
473
+    };
474
+
475
+    /**
476
+     * Enable or disable debugging output.  This primarily enables and
477
+     * disables libmodbus debugging output.
478
+     *
479
+     * @param enable true to enable debugging, false otherwise
480
+     */
481
+    void setDebug(bool enable);
482
+
483
+    /**
484
+     * Indicate whether the connected device is an H8035 or an H8036.
485
+     * The H8036 provides many more data registers.
486
+     *
487
+     * @return true if we are using an H8036, false otherwise.
488
+     */
489
+    bool isH8036()
490
+    {
491
+      return m_isH8036;
492
+    };
493
+
494
+  protected:
495
+    // holding registers
496
+    int readHoldingRegs(HOLDING_REGS_T reg, int len, uint16_t *buf);
497
+    void writeHoldingReg(HOLDING_REGS_T reg, int value);
498
+
499
+    // clear out all stored data
500
+    void clearData();
501
+    
502
+    // MODBUS context
503
+    modbus_t *m_mbContext;
504
+
505
+    // test to see if the connected device is an H8036, and set
506
+    // m_isH8036 appropriately
507
+    void testH8036();
508
+
509
+    // Is this an H8036 (has extended registers)
510
+    bool m_isH8036;
511
+
512
+  private:
513
+    bool m_debugging;
514
+
515
+    // data
516
+
517
+    // H8035 / H8036
518
+    float m_consumptionkWh;
519
+    float m_realPowerkW;
520
+
521
+    // H8036 only
522
+    float m_reactivePowerkVAR;
523
+    float m_apparentPowerkVA;
524
+    float m_powerFactor;
525
+    float m_voltsLineToLine;
526
+    float m_voltsLineToNeutral;
527
+    float m_current; // in amps
528
+    float m_realPowerPhaseAkW;
529
+    float m_realPowerPhaseBkW;
530
+    float m_realPowerPhaseCkW;
531
+    float m_powerFactorPhaseA;
532
+    float m_powerFactorPhaseB;
533
+    float m_powerFactorPhaseC;
534
+    float m_voltsPhaseAB;
535
+    float m_voltsPhaseBC;
536
+    float m_voltsPhaseAC;
537
+    float m_voltsPhaseAN;
538
+    float m_voltsPhaseBN;
539
+    float m_voltsPhaseCN;
540
+    float m_currentPhaseA;
541
+    float m_currentPhaseB;
542
+    float m_currentPhaseC;
543
+    float m_avgRealPowerkW;
544
+    float m_minRealPowerkW;
545
+    float m_maxRealPowerkW;
546
+  };
547
+}

+ 20
- 0
src/h803x/javaupm_h803x.i ファイルの表示

@@ -0,0 +1,20 @@
1
+%module javaupm_h803x
2
+%include "../upm.i"
3
+%include "typemaps.i"
4
+
5
+%{
6
+    #include "h803x.h"
7
+%}
8
+
9
+%include "h803x.h"
10
+
11
+%pragma(java) jniclasscode=%{
12
+    static {
13
+        try {
14
+            System.loadLibrary("javaupm_h803x");
15
+        } catch (UnsatisfiedLinkError e) {
16
+            System.err.println("Native code library failed to load. \n" + e);
17
+            System.exit(1);
18
+        }
19
+    }
20
+%}

+ 8
- 0
src/h803x/jsupm_h803x.i ファイルの表示

@@ -0,0 +1,8 @@
1
+%module jsupm_h803x
2
+%include "../upm.i"
3
+%include "stdint.i"
4
+
5
+%include "h803x.h"
6
+%{
7
+    #include "h803x.h"
8
+%}

+ 12
- 0
src/h803x/pyupm_h803x.i ファイルの表示

@@ -0,0 +1,12 @@
1
+// Include doxygen-generated documentation
2
+%include "pyupm_doxy2swig.i"
3
+%module pyupm_h803x
4
+%include "../upm.i"
5
+%include "stdint.i"
6
+
7
+%feature("autodoc", "3");
8
+
9
+%include "h803x.h"
10
+%{
11
+    #include "h803x.h"
12
+%}