浏览代码

Merge branch 'master' of https://git.server.tsgames.de/Raspberry/solar-monitor

Torsten Simon 2 年之前
父节点
当前提交
1bd5df40f2
共有 12 个文件被更改,包括 812 次插入15 次删除
  1. 2 0
      .gitignore
  2. 1 0
      Tesseract_sevenSegmentsLetsGoDigital
  3. 5 5
      arduino/arduino.ino
  4. 599 0
      dashboard.json
  5. 99 0
      data-writer-opencv.py
  6. 76 6
      data-writer.py
  7. 1 0
      display_ocr
  8. 3 1
      docker-compose.yml
  9. 17 1
      install.sh
  10. 1 0
      pytorch-rpi
  11. 8 2
      src/requirements.txt
  12. 二进制
      torch-1.12.0a0+git67ece03-cp39-cp39-linux_aarch64.whl

+ 2 - 0
.gitignore

@@ -1 +1,3 @@
 *.jpg
+camera/
+camera/

+ 1 - 0
Tesseract_sevenSegmentsLetsGoDigital

@@ -0,0 +1 @@
+Subproject commit a43ae7417e024ab358271b30fa15dc6667d2f2ea

+ 5 - 5
arduino/arduino.ino

@@ -9,11 +9,11 @@ void setup() {
 
 void loop() {
   unsigned int val=abs(analogRead(A0));
-  unsigned long V=round(val * 0.006270 * 1000);
-  Serial.println(V);
-  Serial.println((V * 1000) << 2 | 0x00);
-  rcSwitch.send((V * 1000) << 2 | 0x00, 24);
-  delay(500);  
+  unsigned long U=round(val * 0.006270 * 1000);
+  Serial.println(U);
+  Serial.println(U << 8 | 0x00);
+  rcSwitch.send(U << 8 | 0x00, 24);
+  delay(1000);  
 }
 
 // 244 = 1.53

+ 599 - 0
dashboard.json

@@ -0,0 +1,599 @@
+{
+    "annotations": {
+      "list": [
+        {
+          "builtIn": 1,
+          "datasource": "-- Grafana --",
+          "enable": true,
+          "hide": true,
+          "iconColor": "rgba(0, 211, 255, 1)",
+          "name": "Annotations & Alerts",
+          "type": "dashboard"
+        }
+      ]
+    },
+    "editable": true,
+    "gnetId": null,
+    "graphTooltip": 0,
+    "id": 1,
+    "links": [],
+    "panels": [
+      {
+        "datasource": null,
+        "description": "",
+        "fieldConfig": {
+          "defaults": {
+            "color": {
+              "mode": "thresholds"
+            },
+            "decimals": 1,
+            "mappings": [],
+            "max": 300,
+            "min": 0,
+            "thresholds": {
+              "mode": "absolute",
+              "steps": [
+                {
+                  "color": "red",
+                  "value": null
+                },
+                {
+                  "color": "orange",
+                  "value": 30
+                },
+                {
+                  "color": "yellow",
+                  "value": 100
+                },
+                {
+                  "color": "green",
+                  "value": 160
+                }
+              ]
+            },
+            "unit": "watt"
+          },
+          "overrides": []
+        },
+        "gridPos": {
+          "h": 7,
+          "w": 24,
+          "x": 0,
+          "y": 0
+        },
+        "id": 4,
+        "options": {
+          "reduceOptions": {
+            "calcs": [
+              "lastNotNull"
+            ],
+            "fields": "",
+            "values": false
+          },
+          "showThresholdLabels": false,
+          "showThresholdMarkers": true,
+          "text": {}
+        },
+        "pluginVersion": "7.5.7",
+        "targets": [
+          {
+            "groupBy": [
+              {
+                "params": [
+                  "$__interval"
+                ],
+                "type": "time"
+              },
+              {
+                "params": [
+                  "null"
+                ],
+                "type": "fill"
+              }
+            ],
+            "orderByTime": "ASC",
+            "policy": "default",
+            "query": "from(bucket: \"influxdb\")\n  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\n  |> filter(fn: (r) =>\n    r._measurement == \"solar\"\n  )",
+            "refId": "A",
+            "resultFormat": "time_series",
+            "select": [
+              [
+                {
+                  "params": [
+                    "value"
+                  ],
+                  "type": "field"
+                },
+                {
+                  "params": [],
+                  "type": "mean"
+                }
+              ]
+            ],
+            "tags": []
+          }
+        ],
+        "title": "Current Input",
+        "transformations": [
+          {
+            "id": "calculateField",
+            "options": {
+              "alias": "Power",
+              "binary": {
+                "left": "value {name=\"solar\", type=\"A\"}",
+                "operator": "*",
+                "reducer": "sum",
+                "right": "value {name=\"solar\", type=\"V\"}"
+              },
+              "mode": "binary",
+              "reduce": {
+                "include": [],
+                "reducer": "sum"
+              },
+              "replaceFields": true
+            }
+          }
+        ],
+        "type": "gauge"
+      },
+      {
+        "aliasColors": {},
+        "bars": false,
+        "dashLength": 10,
+        "dashes": false,
+        "datasource": null,
+        "description": "",
+        "fieldConfig": {
+          "defaults": {
+            "unit": "amp"
+          },
+          "overrides": []
+        },
+        "fill": 1,
+        "fillGradient": 0,
+        "gridPos": {
+          "h": 8,
+          "w": 12,
+          "x": 0,
+          "y": 7
+        },
+        "hiddenSeries": false,
+        "id": 6,
+        "legend": {
+          "avg": false,
+          "current": false,
+          "max": false,
+          "min": false,
+          "show": false,
+          "total": false,
+          "values": false
+        },
+        "lines": true,
+        "linewidth": 1,
+        "nullPointMode": "null",
+        "options": {
+          "alertThreshold": true
+        },
+        "percentage": false,
+        "pluginVersion": "7.5.7",
+        "pointradius": 2,
+        "points": false,
+        "renderer": "flot",
+        "seriesOverrides": [],
+        "spaceLength": 10,
+        "stack": false,
+        "steppedLine": false,
+        "targets": [
+          {
+            "groupBy": [
+              {
+                "params": [
+                  "$__interval"
+                ],
+                "type": "time"
+              },
+              {
+                "params": [
+                  "null"
+                ],
+                "type": "fill"
+              }
+            ],
+            "orderByTime": "ASC",
+            "policy": "default",
+            "query": "from(bucket: \"influxdb\")\n  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\n  |> filter(fn: (r) =>\n    r._measurement == \"solar\"\n  )",
+            "refId": "A",
+            "resultFormat": "time_series",
+            "select": [
+              [
+                {
+                  "params": [
+                    "value"
+                  ],
+                  "type": "field"
+                },
+                {
+                  "params": [],
+                  "type": "mean"
+                }
+              ]
+            ],
+            "tags": []
+          }
+        ],
+        "thresholds": [],
+        "timeFrom": null,
+        "timeRegions": [],
+        "timeShift": null,
+        "title": "Ampere",
+        "tooltip": {
+          "shared": true,
+          "sort": 0,
+          "value_type": "individual"
+        },
+        "transformations": [
+          {
+            "id": "filterFieldsByName",
+            "options": {
+              "include": {
+                "names": [
+                  "Time",
+                  "value A"
+                ]
+              }
+            }
+          },
+          {
+            "id": "renameByRegex",
+            "options": {
+              "regex": "value A",
+              "renamePattern": "I"
+            }
+          }
+        ],
+        "type": "graph",
+        "xaxis": {
+          "buckets": null,
+          "mode": "time",
+          "name": null,
+          "show": true,
+          "values": []
+        },
+        "yaxes": [
+          {
+            "$$hashKey": "object:72",
+            "format": "amp",
+            "label": null,
+            "logBase": 1,
+            "max": null,
+            "min": null,
+            "show": true
+          },
+          {
+            "$$hashKey": "object:73",
+            "format": "short",
+            "label": null,
+            "logBase": 1,
+            "max": null,
+            "min": null,
+            "show": true
+          }
+        ],
+        "yaxis": {
+          "align": false,
+          "alignLevel": null
+        }
+      },
+      {
+        "aliasColors": {},
+        "bars": false,
+        "dashLength": 10,
+        "dashes": false,
+        "datasource": null,
+        "description": "",
+        "fieldConfig": {
+          "defaults": {
+            "unit": "volt"
+          },
+          "overrides": []
+        },
+        "fill": 1,
+        "fillGradient": 0,
+        "gridPos": {
+          "h": 8,
+          "w": 12,
+          "x": 12,
+          "y": 7
+        },
+        "hiddenSeries": false,
+        "id": 2,
+        "legend": {
+          "avg": false,
+          "current": false,
+          "max": false,
+          "min": false,
+          "show": false,
+          "total": false,
+          "values": false
+        },
+        "lines": true,
+        "linewidth": 1,
+        "nullPointMode": "null",
+        "options": {
+          "alertThreshold": true
+        },
+        "percentage": false,
+        "pluginVersion": "7.5.7",
+        "pointradius": 2,
+        "points": false,
+        "renderer": "flot",
+        "seriesOverrides": [],
+        "spaceLength": 10,
+        "stack": false,
+        "steppedLine": false,
+        "targets": [
+          {
+            "groupBy": [
+              {
+                "params": [
+                  "$__interval"
+                ],
+                "type": "time"
+              },
+              {
+                "params": [
+                  "null"
+                ],
+                "type": "fill"
+              }
+            ],
+            "orderByTime": "ASC",
+            "policy": "default",
+            "query": "from(bucket: \"influxdb\")\n  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\n  |> filter(fn: (r) =>\n    r._measurement == \"solar\"\n  )",
+            "refId": "A",
+            "resultFormat": "time_series",
+            "select": [
+              [
+                {
+                  "params": [
+                    "value"
+                  ],
+                  "type": "field"
+                },
+                {
+                  "params": [],
+                  "type": "mean"
+                }
+              ]
+            ],
+            "tags": []
+          }
+        ],
+        "thresholds": [],
+        "timeFrom": null,
+        "timeRegions": [],
+        "timeShift": null,
+        "title": "Voltage",
+        "tooltip": {
+          "shared": true,
+          "sort": 0,
+          "value_type": "individual"
+        },
+        "transformations": [
+          {
+            "id": "filterFieldsByName",
+            "options": {
+              "include": {
+                "names": [
+                  "Time",
+                  "value V"
+                ]
+              }
+            }
+          },
+          {
+            "id": "renameByRegex",
+            "options": {
+              "regex": "value V",
+              "renamePattern": "U"
+            }
+          }
+        ],
+        "type": "graph",
+        "xaxis": {
+          "buckets": null,
+          "mode": "time",
+          "name": null,
+          "show": true,
+          "values": []
+        },
+        "yaxes": [
+          {
+            "$$hashKey": "object:72",
+            "format": "volt",
+            "label": null,
+            "logBase": 1,
+            "max": null,
+            "min": null,
+            "show": true
+          },
+          {
+            "$$hashKey": "object:73",
+            "format": "short",
+            "label": null,
+            "logBase": 1,
+            "max": null,
+            "min": null,
+            "show": true
+          }
+        ],
+        "yaxis": {
+          "align": false,
+          "alignLevel": null
+        }
+      },
+      {
+        "aliasColors": {},
+        "bars": false,
+        "dashLength": 10,
+        "dashes": false,
+        "datasource": null,
+        "description": "",
+        "fieldConfig": {
+          "defaults": {},
+          "overrides": []
+        },
+        "fill": 1,
+        "fillGradient": 0,
+        "gridPos": {
+          "h": 9,
+          "w": 24,
+          "x": 0,
+          "y": 15
+        },
+        "hiddenSeries": false,
+        "id": 5,
+        "legend": {
+          "alignAsTable": false,
+          "avg": false,
+          "current": false,
+          "max": false,
+          "min": false,
+          "rightSide": false,
+          "show": false,
+          "total": false,
+          "values": false
+        },
+        "lines": true,
+        "linewidth": 1,
+        "nullPointMode": "null",
+        "options": {
+          "alertThreshold": true
+        },
+        "percentage": false,
+        "pluginVersion": "7.5.7",
+        "pointradius": 2,
+        "points": false,
+        "renderer": "flot",
+        "seriesOverrides": [],
+        "spaceLength": 10,
+        "stack": false,
+        "steppedLine": false,
+        "targets": [
+          {
+            "groupBy": [
+              {
+                "params": [
+                  "$__interval"
+                ],
+                "type": "time"
+              },
+              {
+                "params": [
+                  "null"
+                ],
+                "type": "fill"
+              }
+            ],
+            "orderByTime": "ASC",
+            "policy": "default",
+            "query": "from(bucket: \"influxdb\")\n  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)\n  |> filter(fn: (r) =>\n    r._measurement == \"solar\"\n  )",
+            "refId": "A",
+            "resultFormat": "time_series",
+            "select": [
+              [
+                {
+                  "params": [
+                    "value"
+                  ],
+                  "type": "field"
+                },
+                {
+                  "params": [],
+                  "type": "mean"
+                }
+              ]
+            ],
+            "tags": []
+          }
+        ],
+        "thresholds": [],
+        "timeFrom": null,
+        "timeRegions": [],
+        "timeShift": null,
+        "title": "Power",
+        "tooltip": {
+          "shared": false,
+          "sort": 0,
+          "value_type": "individual"
+        },
+        "transformations": [
+          {
+            "id": "calculateField",
+            "options": {
+              "alias": "Power",
+              "binary": {
+                "left": "value {name=\"solar\", type=\"A\"}",
+                "operator": "*",
+                "reducer": "sum",
+                "right": "value {name=\"solar\", type=\"V\"}"
+              },
+              "mode": "binary",
+              "reduce": {
+                "include": [],
+                "reducer": "sum"
+              },
+              "replaceFields": true
+            }
+          }
+        ],
+        "type": "graph",
+        "xaxis": {
+          "buckets": null,
+          "mode": "time",
+          "name": null,
+          "show": true,
+          "values": []
+        },
+        "yaxes": [
+          {
+            "$$hashKey": "object:105",
+            "format": "watt",
+            "label": null,
+            "logBase": 1,
+            "max": null,
+            "min": null,
+            "show": true
+          },
+          {
+            "$$hashKey": "object:106",
+            "format": "dateTimeAsLocal",
+            "label": null,
+            "logBase": 1,
+            "max": null,
+            "min": null,
+            "show": false
+          }
+        ],
+        "yaxis": {
+          "align": false,
+          "alignLevel": null
+        }
+      }
+    ],
+    "schemaVersion": 27,
+    "style": "dark",
+    "tags": [],
+    "templating": {
+      "list": []
+    },
+    "time": {
+      "from": "now-30m",
+      "to": "now"
+    },
+    "timepicker": {},
+    "timezone": "browser",
+    "title": "Solar",
+    "uid": "jn3v5cV4k",
+    "version": 5
+  }

+ 99 - 0
data-writer-opencv.py

@@ -0,0 +1,99 @@
+import numpy.core.multiarray
+import cv2
+import pytesseract
+import numpy as np
+import time
+from datetime import datetime
+from picamera import PiCamera
+from pytesseract import Output
+
+import cv2
+import pytesseract
+from pytesseract import Output
+import numpy as np
+import re
+def parse(image): 
+    custom_oem=r'--oem 3 --psm 11'
+    # https://github.com/adrianlazaro8/Tesseract_sevenSegmentsLetsGoDigital
+    data = pytesseract.image_to_data(img, lang='lets', config=custom_oem, output_type=Output.DICT)
+    print(data)
+    results = []
+    for i in range(len(data['text'])):
+        text = data['text'][i].strip('.,-_')
+        text = re.sub('[^0-9]', '', text)
+        if text:
+            results.append(text)
+    if len(results) == 2:
+        results = list(map(lambda x: int(x) / 10.,results ))
+        if results[0] < 100 and results[1] < 1000:
+            return results
+    return None
+def thresholding(image):
+    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
+    
+    pixel_values = image.reshape((-1, 1))
+    pixel_values = np.float32(pixel_values)
+    print(pixel_values.shape)
+    # define stopping criteria
+    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
+    # number of clusters (K)
+    k = 3
+    _, labels, (centers) = cv2.kmeans(pixel_values, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
+    # convert back to 8 bit values
+    centers = np.uint8(centers)
+
+    # flatten the labels array
+    labels = labels.flatten()
+    # convert all pixels to the color of the centroids
+    segmented_image = centers[labels.flatten()]
+    segmented_image = segmented_image.reshape(image.shape)
+    
+    # disable only the cluster number 2 (turn the pixel into black)
+    masked_image = np.copy(image)
+    # convert to the shape of a vector of pixel values
+    masked_image = masked_image.reshape((-1, 1))
+    # color (i.e cluster) to disable
+    cluster = 2
+    masked_image[labels != cluster] = [0]
+    # convert back to original shape
+    masked_image = masked_image.reshape(image.shape)
+    
+    return masked_image
+   
+    
+    image = cv2.medianBlur(image,3)
+    #image = np.invert(image)
+    return cv2.threshold(image, 140, 255, cv2.THRESH_BINARY)[1]
+    return image
+def thresholding2(image):
+    
+    image = cv2.medianBlur(image,7)
+    #image = np.invert(image)
+    return image
+ 
+def crop(image):
+    top=314
+    left=230
+    height= 150
+    width=400
+    return image[top : (top + height) , left: (left + width)]
+
+
+
+camera = PiCamera(
+    resolution=(800, 600)
+)
+camera.awb_mode = 'off'
+camera.awb_gains = (1.5, 2.0)
+camera.shutter_speed = 60000
+camera.iso = 800
+while True:
+    file = "/home/pi/solar-monitor/camera/" + str(datetime.now()) + ".jpg"
+    camera.capture(file)
+    print("Captured.")
+    img = cv2.imread(file)
+    img = crop(img)
+    img = thresholding2(img)
+    print(parse(img))
+    cv2.imwrite(file + '_r.jpg', img)
+    time.sleep(2)

+ 76 - 6
data-writer.py

@@ -1,9 +1,79 @@
 import time
 import random
-from influxdb_client import InfluxDBClient
-client = InfluxDBClient(url="http://localhost:8086", token="influxdbTSGAMES", org="raspberry")
-writer = client.write_api()
+from influxdb import InfluxDBClient
+client = InfluxDBClient(host="localhost", port=8086, username="influxdb", password="influxdbTSGAMES")
+client.create_database("influxdb")
+client.switch_database('influxdb')
+#!/usr/bin/env python3
+
+import argparse
+import signal
+import sys
+import time
+import logging
+
+from rpi_rf import RFDevice
+VOLTAGE = 0
+AMPERE = 1
+
+# min samples in a row stable to be accepted as new value
+STABLE_COUNT = 3
+# max diff which is considered stable between new values
+STABLE_DIFF_THRESHOLD = .1
+rfdevice = None
+
+# pylint: disable=unused-argument
+def exithandler(signal, frame):
+    rfdevice.cleanup()
+    sys.exit(0)
+
+logging.basicConfig(level=logging.INFO)
+
+parser = argparse.ArgumentParser(description='Receives a decimal code via a 433/315MHz GPIO device')
+parser.add_argument('-g', dest='gpio', type=int, default=27,
+                    help="GPIO pin (Default: 27)")
+args = parser.parse_args()
+
+signal.signal(signal.SIGINT, exithandler)
+rfdevice = RFDevice(args.gpio, rx_tolerance=80)
+rfdevice.enable_rx()
+timestamp = None
+logging.info("Listening for codes on GPIO " + str(args.gpio))
+previous_values = {}
+counts = {}
 while True:
-    writer.write("influxdb","raspberry", ["solar,type=A value=" + str(random.randrange(10))])
-    writer.write("influxdb","raspberry", ["solar,type=V value=12"])
-    time.sleep(1)
+    if rfdevice.rx_code_timestamp != timestamp:
+        timestamp = rfdevice.rx_code_timestamp
+        code = rfdevice.rx_code
+        codeType = code & 0xff
+        value = (code >> 8) / 1000.
+        U = 0
+        I = 0
+        if value:
+            if codeType in previous_values and abs(previous_values[codeType]-value) <= STABLE_DIFF_THRESHOLD:
+                counts[codeType] += 1
+            else:
+                counts[codeType] = 0
+            previous_values[codeType] = value
+        logging.info("Data Received: " + str(code) + "/" + str(codeType) + " / " + str(value))
+        if codeType in counts and counts[codeType] >= STABLE_COUNT:
+            if codeType == VOLTAGE or True:
+                U = value
+                logging.info("Stable Voltage:" +str(U))
+                client.write_points([
+                    {
+                        "measurement": "solar",
+                        "tags": {
+                            "type": "U"
+                        },
+                        "fields": {
+                            "value": U
+                        }
+                    }
+                ], time_precision='ms')
+            if codeType == AMPERE:
+                logging.info("Ampere")
+                I = value
+            
+    time.sleep(0.05)
+rfdevice.cleanup()

+ 1 - 0
display_ocr

@@ -0,0 +1 @@
+Subproject commit 27f938105a3c7c9d5d0d2493611422144f661bec

+ 3 - 1
docker-compose.yml

@@ -16,7 +16,8 @@ services:
         - grafana-data:/var/lib/grafana
         
   influxdb:
-    image: influxdb:2.4
+    #image: influxdb:2.0
+    image: arm32v7/influxdb:latest
     container_name: influxdb
     ports:
       - "8083:8083"
@@ -24,6 +25,7 @@ services:
       - "8090:8090"
       - "2003:2003"
     environment:
+      INFLUXDB_HTTP_FLUX_ENABLED: true
       DOCKER_INFLUXDB_INIT_MODE: setup
       DOCKER_INFLUXDB_INIT_USERNAME: influxdb
       DOCKER_INFLUXDB_INIT_PASSWORD: influxdbTSGAMES

+ 17 - 1
install.sh

@@ -1,4 +1,20 @@
 #!/bin/sh
 
-sudo apt-get update && apt-get install python3-pip
+sudo apt-get update
+sudo apt-get install python3-pip tesseract-ocr python-opencv build-essential cmake pkg-config libjpeg-dev libtiff5-dev libjasper-dev libpng-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libfontconfig1-dev libcairo2-dev libgdk-pixbuf2.0-dev libpango1.0-dev libgtk2.0-dev libgtk-3-dev libatlas-base-dev gfortran libhdf5-dev libhdf5-serial-dev libhdf5-103 python3-pyqt5 python3-dev -y
+
 pip3 install -r requirements.txt
+pip3 install -U numpy
+git clone https://github.com/arturaugusto/display_ocr
+sudo cp display_ocr/letsgodigital/* /usr/share/tesseract-ocr/4.00/tessdata/
+git clone https://github.com/adrianlazaro8/Tesseract_sevenSegmentsLetsGoDigital && cd Tesseract_sevenSegmentsLetsGoDigital
+sudo mv 'Trained data'/* /usr/share/tesseract-ocr/4.00/tessdata/
+docker-compose up -d
+(crontab -l 2>/dev/null; echo "@reboot python3 /home/pi/solar-monitor/data-writer.py") | crontab -
+# python3 data-writer.py
+echo "Reboot pi to complete setup and start the data job or run 'python3 /home/pi/solar-monitor/data-writer.py'"
+
+
+# UNSORTED
+git clone https://github.com/ljk53/pytorch-rpi && cd pytorch-rpi
+LIBTORCH_VARIANT=armv7l-cxx11-abi-shared-without-deps ./build_libtorch.sh

+ 1 - 0
pytorch-rpi

@@ -0,0 +1 @@
+Subproject commit 92ef25e99834dc705dcd8e6f2be1facdd6846d21

+ 8 - 2
src/requirements.txt

@@ -1,2 +1,8 @@
-influxdb-client
-rpi-rf
+influxdb-client # this is for 2.x
+influxdb
+rpi-rf
+opencv-python==4.5.3.56
+pillow
+pytesseract
+imutils
+picamera

二进制
torch-1.12.0a0+git67ece03-cp39-cp39-linux_aarch64.whl