[PYTHON] Ich habe versucht, den Stromverbrauch meines Hauses mit Nature Remo E lite zu visualisieren

Einführung

Mit "Nature Remo E lite", mit dem die zu Hause verbrauchte Strommenge in Echtzeit erfasst werden kann, Ich habe ein Dashboard erstellt, das den Stromverbrauch visualisiert watt.png Durch Anzeigen des Nutzungsstatus der von Nature Remo erworbenen Klimaanlage, ** Sie sehen die Beziehung zwischen Stromverbrauch und Ein- und Ausschalten der Klimaanlage auf einen Blick! ** **. Ich bin der Meinung, dass wir einen Schritt nach vorne gemacht haben, um ein energiesparendes Haus zu realisieren.

IoT und Smart Meter

Es ist lange her, dass das Wort ** IoT ** zu einem Boom wurde. Gleichzeitig wird die Schwierigkeit, mit IoT Wert zu schaffen, immer größer, und ich habe das Gefühl, dass die Augen der Welt für IoT immer strenger werden.

Die folgende Abbildung zeigt die von Gartner angekündigte Version von "Hype Cycle Diagram" für 2019. Das Internet der Dinge ist in eine Phase der Ernüchterung eingetreten. 191031_gartner_hypecycle_2019.png

Insbesondere für IoT-Produkte für den Heimgebrauch, mit Ausnahme von Smart-Lautsprechern und Smart-Fernbedienungen, die weltweit vorherrschen, Ich habe das Gefühl, dass es viele Dinge gibt, die nicht viel zu verdienen scheinen, selbst wenn sie schlauer gemacht werden.

Unter diesen Umständen ist das IoT-Produkt, das Elektrizitätsunternehmen ständig einführen, ** Smart Meter **. Wenn wir den Stromverbrauch visualisieren und effizient nutzen können, was für Haus und Gesellschaft erhebliche Kosten verursacht, Es basiert auf der Idee, dass ** "Wert" ** erstellt werden kann.

Was ist Nature Remo E lite?

Das oben genannte Smart Meter überträgt Stromverbrauchsdaten über einen drahtlosen Standard namens WiSUN. Diese Daten können auch von Produkten von Drittanbietern empfangen und verwendet werden (B-Root-Service).

Von diesen Produkten von Drittanbietern ** Stromverbrauchsdatenempfangsgerät **, entwickelt von Nature, bekannt für seine intelligente Fernbedienung "Nature Remo"

** Nature Remo E lite **. remo-e-lite.12.jpg

Was du tun kannst

Mit Nature Remo E lite können Sie:

・ Überprüfen Sie den Stromverbrauch mit der App

Sie können den aktuellen Stromverbrauch und ein einfaches Verlaufsdiagramm mit der offiziellen App überprüfen. Screenshot_20200812-174424.png

・ Erfassung von Stromverbrauchsdaten mit API

Stromverbrauchsdaten können mithilfe der API programmgesteuert verarbeitet werden. Grundsätzlich kann es von Nature Remo gemeinsam genutzte API bezogen werden.

GET /1/appliances

Mit dem Befehl können Sie die Stromverbrauchsdaten von Remo E lite sowie die Gerätedaten von Nature Remo abrufen.

API-Ausführungsbeispiel

Geben Sie unter Linux den folgenden Befehl ein ([Informationen zum Ausstellen von Zugriffstoken finden Sie hier](https://qiita.com/t-chi/items/01b9a9b98fbccef880c3#natureremo%E3%81%AE%E3%82%A2%E3%82%AF % E3% 82% BB% E3% 82% B9% E3% 83% 88% E3% 83% BC% E3% 82% AF% E3% 83% B3% E3% 82% 92% E7% 99% BA% E8 % A1% 8C% E3% 81% 99% E3% 82% 8B))

curl -X GET "https://api.nature.global/1/appliances" -k --header "Authorization:Inhaberzugriffstoken"

Der folgende JSON wird zurückgegeben

[
    {
    :
Sonstige Geräteinformationen
    :
    },
    {
        "id": "****",
        "device": {
            "name": "Remo E lite",
            "id": "****",
            "created_at": "2020-06-09T17:16:06Z",
            "updated_at": "2020-06-17T13:55:50Z",
            "mac_address": "**:**:**:**:**:**",
            "bt_mac_address": "**:**:**:**:**:**",
            "serial_number": "****",
            "firmware_version": "Remo-E-lite/1.1.3",
            "temperature_offset": 0,
            "humidity_offset": 0
        },
        "model": {
            "id": "****",
            "manufacturer": "",
            "name": "Smart Meter",
            "image": "ico_smartmeter"
        },
        "type": "EL_SMART_METER",
        "nickname": "Smart Meter",
        "image": "ico_smartmeter",
        "settings": null,
        "aircon": null,
        "signals": [],
        "smart_meter": {
            "echonetlite_properties": [
                {
                    "name": "cumulative_electric_energy_effective_digits",
                    "epc": 215,
                    "val": "7",
                    "updated_at": "2020-08-12T10:09:14Z"
                },
                {
                    "name": "normal_direction_cumulative_electric_energy",
                    "epc": 224,
                    "val": "294263",
                    "updated_at": "2020-08-12T10:09:14Z"
                },
                {
                    "name": "cumulative_electric_energy_unit",
                    "epc": 225,
                    "val": "2",
                    "updated_at": "2020-08-12T10:09:14Z"
                },
                {
                    "name": "measured_instantaneous",
                    "epc": 231,
                    "val": "464",
                    "updated_at": "2020-08-12T10:09:14Z"
                }
            ]
        }
    },
    {
    :
Sonstige Geräteinformationen
    :
    }
]

Smart Meter Informationen "smart_meter": Siehe "val" im Abschnitt "echonetlite_properties". Die beiden folgenden Abschnitte sind von besonderer Bedeutung.

normal_direction_cumulative_electric_energy: Bisheriger Gesamtstromverbrauch (Einheit: 0,01 kWh) gemessen_momentan: Aktueller Stromverbrauch (Einheit: Watt)

Im Fall des obigen JSON beträgt der Gesamtstromverbrauch 2942,63 kWh und der aktuelle Stromverbrauch 464 Watt.

** Dieses Mal verwenden wir diese API, um die Beziehung zwischen Stromverbrauch und Ein / Aus der Klimaanlage in einem Diagramm anzuzeigen, wie im oberen Bild gezeigt. **

Dinge notwendig

** ・ Nature Remo E lite ** ** ・ Normal Nature Remo ** ‥ Erforderlich, um Informationen zum Ein- und Ausschalten von Klimaanlagen zu erhalten ** ・ Raspberry Pi ** (diesmal wird Raspberry Pi3 Modell B verwendet) ** ・ Python-Ausführungsumgebung ** (diesmal wird voreingestelltes Python 3.7.3 verwendet) ** ・ Google-Konto ** (erforderlich, um Tabellenkalkulation und Datenportal zu verwenden)

Verfahren

Führen Sie die folgenden Schritte aus, um ein Dashboard für den Stromverbrauch zu erstellen.

** 1. Beantragen Sie den B-Route-Service beim Elektrizitätsunternehmen 2. Nature Remo E lite Grundeinstellungen 3. Erstellen eines Protokollierungssystems mit Raspberry Pi 4. Erstellen eines Stromverbrauchs-Dashboards **

1. Beantragen Sie den B-Route-Service beim Elektrizitätsunternehmen

Um die Daten des Smart Meters zu erfassen, muss der B-Route-Service bei dem verwendeten Elektrizitätsunternehmen beantragt werden. (Selbst wenn Sie einen Dienst wie au Denki zur Stromliberalisierung nutzen, müssen Sie sich anscheinend bei einem regionalen Energieversorgungsunternehmen wie TEPCO bewerben.)

Bewerben Sie sich auf der Homepage des Energieversorgers

In meinem Fall habe ich mich auf der Website der Kansai Electric Power Group unten beworben. https://www.kansai-td.co.jp/application/smart-meter/low-pressure/index.html

Weitere Bereiche für Energieversorgungsunternehmen finden Sie im Folgenden https://chasuke.com/nremoe/

Als ich mich bewarb, erhielt ich einen Anruf und sagte, dass eine einfache Konstruktion (kostenlos) erforderlich sei. Daher sollte der Zeitplan angepasst und dann die Konstruktion ausgeführt werden.

Ob eine Konstruktion erforderlich ist oder nicht, hängt vom Installationsstatus des Smart Meters des Hauses ab. Ab 2020 scheinen landesweit etwa zwei Drittel der Haushalte zu intelligenten Zählern zu werden. ・ Für Haushalte, die keine intelligenten Zähler sind, können Sie bei der oben genannten Anwendung vorrangig einen Ersatz beantragen. ・ Auch wenn es sich um ein intelligentes Messgerät handelt, sind möglicherweise zusätzliche Arbeiten wie bei mir erforderlich. Es scheint, dass.

B Empfangen der Root-Service-ID und des Kennworts

Wenn der oben genannte Antrag und die Konstruktion abgeschlossen sind, sendet Ihnen das Energieversorgungsunternehmen die B-Route-Service-ID und das Kennwort per Post. Bei TEPCO wird das Passwort per E-Mail gesendet, und die Versandmethode scheint je nach Region unterschiedlich zu sein (auf jeden Fall denke ich, dass es sich entweder um E-Mail oder E-Mail handelt).

2. Nature Remo E lite Grundeinstellungen

Stecken Sie das Nature Remo E lite in die Steckdose

Stecken Sie das Nature Remo E lite in die Steckdose. Ich hatte das Gefühl, dass das Anschließen an eine Steckdose in der Nähe der Telefonzentrale bei einer späteren Synchronisierung oft besser funktioniert. IMG_20200812_172047.jpg

Laden Sie die Nature Remo App herunter

Laden Sie die App von der folgenden Website auf Ihr Smartphone herunter und installieren Sie sie. android iOS

Grundeinstellung

Befolgen Sie grundsätzlich die Anweisungen der App, um mit den Grundeinstellungen fortzufahren. Wenn Sie unterwegs nach einem Ausweis und einem Passwort gefragt werden, geben Sie den Inhalt des Stromversorgungsunternehmens ein.

Manchmal schlägt es fehl, wenn mit einem Messgerät oder WiFi synchronisiert wird, aber ich Im Fall von hat es oft funktioniert, wenn ich es mehrmals versucht habe.

3. Erstellen eines Protokollierungssystems mit Raspberry Pi

Das zuvor entwickelte Sensordaten-Protokollierungssystem wird verwendet. Bitte führen Sie zunächst den Inhalt dieses Artikels aus (es ist lang, aber ich würde es begrüßen, wenn Sie sich mit mir in Verbindung setzen könnten)

Diesmal, um das oben genannte System mit Nature Remo E lite kompatibel zu machen Sie müssen remo.py und sensor_to_spreadsheet.py neu schreiben. Bitte schreiben Sie jedes wie folgt um. (Entspricht der Operation zum Einfügen des im obigen [API-Ausführungsbeispiel] zurückgegebenen JSON in das Protokollierungsziel.)

remo.py


import json
import requests
import glob
import pandas as pd

#Remo Datenerfassungsklasse
class GetRemoData():
    def get_sensor_data(self, Token, API_URL):
        headers = {
            'accept': 'application/json',
            'Authorization': 'Bearer ' + Token,
        }
        response = requests.get(f"{API_URL}/1/devices", headers=headers)
        rjson = response.json()
        return self._decodeSensorData(rjson)

    def get_aircon_power_data(self, Token, API_URL):
        headers = {
            'accept': 'application/json',
            'Authorization': 'Bearer ' + Token,
        }
        response = requests.get(f"{API_URL}/1/appliances", headers=headers)
        rjson = response.json()
        return self._decodeAirconPowerData(rjson)

    def calc_human_motion(self, Human_last, csvdir):
        filelist = glob.glob(f"{csvdir}/*/*.csv")
        if len(filelist) == 0:
            return 0
        filelist.sort()
        df = pd.read_csv(filelist[-1])
        if df.Human_last[len(df) - 1] != Human_last:
            return 1
        else:
            return 0

    #Extrahieren Sie Sensordaten und konvertieren Sie sie in das Diktatformat
    def _decodeSensorData(self, rjson):
        for device in rjson:
            #Remo-Daten
            if device['firmware_version'].split('/')[0] == 'Remo':
                sensorValue = {
                    'SensorType': 'Remo_Sensor',
                    'Temperature': device['newest_events']['te']['val'],
                    'Humidity': device['newest_events']['hu']['val'],
                    'Light': device['newest_events']['il']['val'],
                    'Human_last': device['newest_events']['mo']['created_at']
                }
        return sensorValue

    #Extrahieren Sie die Daten der Klimaanlage und der Stromversorgung und konvertieren Sie sie in das Diktatformat
    def _decodeAirconPowerData(self, rjson):
        Value = {}
        for appliance in rjson:
            #Klimaanlage
            if appliance['type'] == 'AC':
                Value['TempSetting'] = appliance['settings']['temp']
                Value['Mode'] = appliance['settings']['mode']
                Value['AirVolume'] = appliance['settings']['vol']
                Value['AirDirection'] = appliance['settings']['dir']
                Value['Power'] = appliance['settings']['button']
            #Leistungsdaten des Smart Meters
            elif appliance['type'] == 'EL_SMART_METER':
                for meterValue in appliance['smart_meter']['echonetlite_properties']:
                    if meterValue['name'] == 'normal_direction_cumulative_electric_energy':
                        Value['CumulativeEnergy'] = float(meterValue['val'])/100
                    elif meterValue['name'] == 'measured_instantaneous':
                        Value['Watt'] = int(meterValue['val'])        
        #Wenn der Wert nicht abgerufen werden kann, setzen Sie ihn auf Keine.
        if len(Value) == 0:
            Value = None
        return Value

Die Stromverbrauchsdaten werden mit den oben genannten Methoden "get_aircon_power_data" und "_decodeAirconPowerData" erfasst.

sensors_to_spreadsheet.py


from bluepy import btle
from omron_env import OmronBroadcastScanDelegate, GetOmronConnectModeData
from inkbird_ibsth1 import GetIBSTH1Data
from switchbot import SwitchbotScanDelegate
from remo import GetRemoData
from mesh import GetMeshFromSpreadsheet
from datetime import datetime, timedelta
import os
import csv
import configparser
import pandas as pd
import requests
import logging
import subprocess
import pymongo
from pit import Pit

#Globale Variablen(Erfassungszeit)
global masterdate

######Erfassung von Werten für den OMRON-Umgebungssensor (BAG-Typ)######
def getdata_omron_bag(device):
    #Maximales Gerät, wenn kein Wert verfügbar ist.Wiederholen Wiederholen Sie den Scan
    for i in range(device.Retry):
        #omron_Stellen Sie den Delegierten für die Sensorwerterfassung von env so ein, dass er zur Scan-Zeit ausgeführt wird
        scanner = btle.Scanner().withDelegate(OmronBroadcastScanDelegate())
        #Scannen, um den Sensorwert zu erhalten
        try:
            scanner.scan(device.Timeout)
        #Wenn beim Scannen eine Fehlermeldung angezeigt wird, starten Sie den Bluetooth-Adapter neu
        except:
            restart_hci0(device.DeviceName)
        #Beenden Sie die Schleife, wenn der Wert erhalten werden kann
        if scanner.delegate.sensorValue is not None:
            break
        #Wenn der Wert nicht abgerufen werden kann, schreiben Sie ihn in das Protokoll
        else:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, timeout{device.Timeout}]')
    
    #Wenn der Wert erhalten werden kann, speichern Sie die POST-Daten in dict
    if scanner.delegate.sensorValue is not None:
        #Daten an POST
        data = {        
            'DeviceName': device.DeviceName,        
            'Date_Master': masterdate,
            'Date': datetime.today(),
            'Temperature': scanner.delegate.sensorValue['Temperature'],
            'Humidity': scanner.delegate.sensorValue['Humidity'],
            'Light': scanner.delegate.sensorValue['Light'],
            'UV': scanner.delegate.sensorValue['UV'],
            'Pressure': scanner.delegate.sensorValue['Pressure'],
            'Noise': scanner.delegate.sensorValue['Noise'],
            'BatteryVoltage': scanner.delegate.sensorValue['BatteryVoltage']
        }
        return data
    #Wenn der Wert nicht abgerufen werden konnte, protokollieren Sie die Ausgabe und starten Sie den Bluetooth-Adapter neu
    else:
        logging.error(f'cannot get data [date{str(masterdate)}, device{device.DeviceName}, timeout{device.Timeout}]')
        restart_hci0(device.DeviceName)
        return None

######Datenerfassung des OMRON-Umgebungssensors (USB-Typ)######
def getdata_omron_usb(device):
    #Maximales Gerät, wenn kein Wert verfügbar ist.Wiederholen Wiederholen Sie den Scan
    for i in range(device.Retry):
        try:
            sensorValue = GetOmronConnectModeData().get_env_usb_data(device.MacAddress)
        #Protokollausgabe, wenn ein Fehler auftritt
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}]')
            sensorValue = None
            continue
        else:
            break
    
    #Wenn der Wert erhalten werden kann, speichern Sie die POST-Daten in dict
    if sensorValue is not None:
        #Daten an POST
        data = {        
            'DeviceName': device.DeviceName,        
            'Date_Master': masterdate,
            'Date': datetime.today(),
            'Temperature': sensorValue['Temperature'],
            'Humidity': sensorValue['Humidity'],
            'Light': sensorValue['Light'],
            'Pressure': sensorValue['Pressure'],
            'Noise': sensorValue['Noise'],
            'eTVOC': sensorValue['eTVOC'],
            'eCO2': sensorValue['eCO2']
        }
        return data
    #Wenn der Wert nicht abgerufen werden konnte, protokollieren Sie die Ausgabe und starten Sie den Bluetooth-Adapter neu
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}]')
        restart_hci0(device.DeviceName)
        return None

######Inkbird IBS-TH1 Datenerfassung######
def getdata_ibsth1(device):
    #Maximales Gerät, wenn kein Wert verfügbar ist.Wiederholen Wiederholen Sie den Scan
    for i in range(device.Retry):
        try:
            sensorValue = GetIBSTH1Data().get_ibsth1_data(device.MacAddress, device.SensorType)
        #Protokollausgabe, wenn ein Fehler auftritt
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}]')
            sensorValue = None
            continue
        else:
            break

    if sensorValue is not None:
        #Daten an POST
        data = {        
            'DeviceName': device.DeviceName,        
            'Date_Master': masterdate,
            'Date': datetime.today(),
            'Temperature': sensorValue['Temperature'],
            'Humidity': sensorValue['Humidity']
        }
        return data
    #Wenn der Wert nicht abgerufen werden konnte, protokollieren Sie die Ausgabe und starten Sie den Bluetooth-Adapter neu
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}]')
        restart_hci0(device.DeviceName)
        return None

######SwitchBot-Thermohygrometer-Datenerfassung######
def getdata_switchbot_thermo(device):
    #Maximales Gerät, wenn kein Wert verfügbar ist.Wiederholen Wiederholen Sie den Scan
    for i in range(device.Retry):
        #Stellen Sie den Switchbot-Sensorwert-Erfassungsdelegierten ein
        scanner = btle.Scanner().withDelegate(SwitchbotScanDelegate(str.lower(device.MacAddress)))
        #Scannen, um den Sensorwert zu erhalten
        try:
            scanner.scan(device.Timeout)
        #Wenn beim Scannen eine Fehlermeldung angezeigt wird, starten Sie den Bluetooth-Adapter neu
        except:
            restart_hci0(device.DeviceName)
        #Beenden Sie die Schleife, wenn der Wert erhalten werden kann
        if scanner.delegate.sensorValue is not None:
            break
        #Wenn der Wert nicht abgerufen werden kann, schreiben Sie ihn in das Protokoll
        else:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, timeout{device.Timeout}]')
    
    #Wenn der Wert erhalten werden kann, speichern Sie die POST-Daten in dict
    if scanner.delegate.sensorValue is not None:
        #Daten an POST
        data = {        
            'DeviceName': device.DeviceName,
            'Date_Master': masterdate,
            'Date': datetime.today(),
            'Temperature': scanner.delegate.sensorValue['Temperature'],
            'Humidity': float(scanner.delegate.sensorValue['Humidity']),
            'BatteryVoltage': scanner.delegate.sensorValue['BatteryVoltage']
        }
        return data
    #Wenn nicht, geben Sie das Protokoll aus und starten Sie den Bluetooth-Adapter neu
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}, timeout{device.Timeout}]')
        restart_hci0(device.DeviceName)
        return None

######Nature Remo Datenerfassung######
def getdata_remo(device, csvpath):
    #Maximales Gerät, wenn der Sensordatenwert nicht verfügbar ist.Wiederholen Wiederholen Sie den Scan
    for i in range(device.Retry):
        try:
            sensorValue = GetRemoData().get_sensor_data(device.Token, device.API_URL)
        #Protokollausgabe, wenn ein Fehler auftritt
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, sensor]')
            sensorValue = None
            continue
        else:
            break
    #Maximales Gerät, wenn keine Werte für Klimaanlage und Leistungsdaten verfügbar sind.Wiederholen Wiederholen Sie den Scan
    for i in range(device.Retry):
        try:
            airconPowerValue = GetRemoData().get_aircon_power_data(device.Token, device.API_URL)
        #Protokollausgabe, wenn ein Fehler auftritt
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, aircon]')
            sensorValue = None
            continue
        else:
            break
        
    #Wenn der Wert erhalten werden kann, speichern Sie die POST-Daten in dict
    if sensorValue is not None:
        #Sensordaten
        data = {        
            'DeviceName': device.DeviceName,        
            'Date_Master': masterdate,
            'Date': datetime.today(),
            'Temperature': sensorValue['Temperature'],
            'Humidity': float(sensorValue['Humidity']),
            'Light': sensorValue['Light'],
            'Human_last': sensorValue['Human_last'],
            'HumanMotion': GetRemoData().calc_human_motion(sensorValue['Human_last'], f'{csvpath}/{device.DeviceName}')
        }
        #Klimaanlage & Leistungsdaten
        if airconPowerValue is not None:
            data['TempSetting'] = int(airconPowerValue['TempSetting'])
            data['AirconMode'] = airconPowerValue['Mode']
            data['AirVolume'] = airconPowerValue['AirVolume']
            data['AirDirection'] = airconPowerValue['AirDirection']
            data['AirconPower'] = airconPowerValue['Power']
            if data['AirconPower'] == "":
                data['AirconPower'] = 'power-on_maybe'
            #Leistung
            if 'CumulativeEnergy' in airconPowerValue:
                data['CumulativeEnergy'] = float(airconPowerValue['CumulativeEnergy'])
            if 'Watt' in airconPowerValue:
                data['Watt'] = int(airconPowerValue['Watt'])
        return data
    #Wenn nicht, Protokollausgabe (Da dies über WLAN erfolgt, wird der Bluetooth-Adapter nicht neu gestartet.)
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}]')
        return None

######CSV-Ausgabe von Daten######
def output_csv(data, csvpath):
    dvname = data['DeviceName']
    monthstr = masterdate.strftime('%Y%m')
    #Name des Ausgabeordnerordners
    outdir = f'{csvpath}/{dvname}/{masterdate.year}'
    #Wenn der Ausgabezielordner nicht vorhanden ist, erstellen Sie einen neuen
    os.makedirs(outdir, exist_ok=True)
    #Pfad der Ausgabedatei
    outpath = f'{outdir}/{dvname}_{monthstr}.csv'
    
    #Erstellen Sie eine neue Ausgabedatei, wenn diese nicht vorhanden ist
    if not os.path.exists(outpath):        
        with open(outpath, 'w') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writeheader()
            writer.writerow(data)
    #Fügen Sie eine Zeile hinzu, wenn die Ausgabedatei vorhanden ist
    else:
        with open(outpath, 'a') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writerow(data)

######Prozess des Hochladens in eine Google-Tabelle######
def output_spreadsheet(all_values_dict_str):
    #API-URL
    url = 'Hier aufgeführte GAS-API-URL'
    #POST-Daten an API
    response = requests.post(url, json=all_values_dict_str)
    print(response.text)

######Neustart des Bluetooth-Adapters######
def restart_hci0(devicename):
    passwd = 'Geben Sie das RaspberryPi-Passwort ein'#Fügen Sie bei Bedarf eine Verschleierung hinzu
    subprocess.run(('sudo','-S','hciconfig','hci0','down'), input=passwd, check=True)
    subprocess.run(('sudo','-S','hciconfig','hci0','up'), input=passwd, check=True)
    logging.error(f'restart bluetooth adapter [date{str(masterdate)}, device{devicename}]')


######Maine######
if __name__ == '__main__':
    #Startzeit bekommen
    startdate = datetime.today()
    #Runden Sie die Startzeit in Minuten ab
    masterdate = startdate.replace(second=0, microsecond=0)   
    if startdate.second >= 30:
        masterdate += timedelta(minutes=1)

    #Konfigurationsdatei und Geräteliste lesen
    cfg = configparser.ConfigParser()
    cfg.read('./config.ini', encoding='utf-8')
    df_devicelist = pd.read_csv('./DeviceList.csv')
    #Gesamtzahl der Sensoren und erfolgreiche Datenerfassung
    sensor_num = len(df_devicelist)
    success_num = 0

    #Protokollinitialisierung
    logname = f"/sensorlog_{str(masterdate.strftime('%y%m%d'))}.log"
    logging.basicConfig(filename=cfg['Path']['LogOutput'] + logname, level=logging.INFO)

    #Diktat für das Speichern aller erfassten Daten
    all_values_dict = None
    #Zeichenkettenversion des obigen Diktats (für GAS Post, da der Datum / Uhrzeit-Typ nicht in JSON konvertiert werden kann)
    all_values_dict_str = None

    #Startzeit der Datenerfassung
    scan_start_date = datetime.today()

    ######Datenerfassung für jedes Gerät######
    for device in df_devicelist.itertuples():
        #BAG-Typ des Omron-Umgebungssensors (BroadCast-Verbindung)
        if device.SensorType in ['Omron_BAG_EP','Omron_BAG_IM']:
            data = getdata_omron_bag(device)
        #Omron-Umgebungssensor USB-Typ (Verbindung im Verbindungsmodus)
        elif device.SensorType in ['Omron_USB_EP','Omron_USB_IM']:
            data = getdata_omron_usb(device)
        #Inkbird IBS-TH1
        elif device.SensorType in ['Inkbird_IBSTH1mini','Inkbird_IBSTH1']:
            data = getdata_ibsth1(device)
        #SwitchBot Thermo-Hygrometer
        elif device.SensorType == 'SwitchBot_Thermo':
            data = getdata_switchbot_thermo(device)
        #remo
        elif device.SensorType == 'Nature_Remo':
            data = getdata_remo(device, cfg['Path']['CSVOutput'])
        #mesh
        elif device.SensorType == 'Sony_MeshHuman':
            data = getdata_mesh_human(device)
        #Andere als die oben genannten
        else:
            data = None        

        #Wenn Daten vorhanden sind, fügen Sie sie zu Dict hinzu, um alle Daten zu speichern und CSV auszugeben
        if data is not None:
            #all_values_Erstellen Sie ein neues Wörterbuch, wenn dict Keine ist
            if all_values_dict is None:
                #all_values_Erstellen Sie ein Diktat (weil es das erste ist, Datum_Meister und Datum_ScanStart wird ebenfalls hinzugefügt.
                all_values_dict = {'Date_Master':data['Date_Master'], 'Date_ScanStart':scan_start_date}
                all_values_dict.update(dict([(data['DeviceName']+'_'+k, v) for k,v in data.items() if k != 'Date_Master']))
                #Konvertieren Sie Daten in Zeichenfolgen und alle_values_dict_erstellen str(Datum, weil es das erste ist_ScanStart hinzugefügt)
                data_str = dict([(k, str(v)) for k,v in data.items()])
                data_str['Date_ScanStart'] = str(scan_start_date)
                all_values_dict_str = {data_str['DeviceName']: data_str}
            #all_values_Zum vorhandenen Wörterbuch hinzufügen, wenn dict nicht None ist
            else:
                #all_values_Zum Diktat hinzugefügt (Datum, da es nicht das erste ist_Meister ausgeschlossen)
                all_values_dict.update(dict([(data['DeviceName']+'_'+k, v) for k,v in data.items() if k != 'Date_Master']))
                #all_values_dict_Zu str hinzufügen
                data_str = dict([(k, str(v)) for k,v in data.items()])
                all_values_dict_str[data_str['DeviceName']] = data_str

            #CSV-Ausgabe
            output_csv(data_str, cfg['Path']['CSVOutput'])
            #Erfolgszahl plus
            success_num+=1

    ######Prozess des Hochladens in eine Google-Tabelle######
    output_spreadsheet(all_values_dict_str)

    #Protokollausgabe des Verarbeitungsende
    logging.info(f'[masterdate{str(masterdate)} startdate{str(startdate)} enddate{str(datetime.today())} success{str(success_num)}/{str(sensor_num)}]')

Abgesehen davon, dass es möglich ist, Remo E lite-Daten zu erfassen, haben wir einige Verbesserungen vorgenommen, aber Ich denke, dass es ein Level ist, über das Sie sich im tatsächlichen Betrieb keine Sorgen machen müssen.

Wenn die Einstellungsdatei DeviceList.csv NatureRemos enthält (API_URL und Token müssen eingegeben werden), Für Remo E lite sind keine neuen Ergänzungen erforderlich.

Wenn Sie mit der Protokollierung mit cron beginnen, wie im roten Rahmen unten gezeigt, Gerätename_CumulativeEnergy: Gesamtstromverbrauch (Einheit: kWh) Gerätename_Watt: Aktueller Stromverbrauch (Einheit: Watt) Es werden zwei Arten von Feldern hinzugefügt. spreadsheet_remoelite.png

Sie können sehen, dass der Stromverbrauch sofort ansteigt, wenn die Klimaanlage eingeschaltet wird. Lassen Sie uns im nächsten Kapitel diese Situation grafisch darstellen.

4. Erstellen eines Stromverbrauchs-Dashboards

Google Data Portal ist ein Dashboard, das in der Cloud bearbeitet und angezeigt werden kann. Verwenden Sie dieses Tool, um ein Dashboard zu erstellen, das die Beziehung zwischen Stromverbrauch und Ein / Aus der Klimaanlage anzeigt.

Neuen Bericht erstellen

1_dataportal.png ** Geben Sie eine Google-Tabelle als Datenverbindungsziel an ** 2_connect_spreadsheet.png ** Wenn Sie um Genehmigung gebeten werden, drücken Sie die Genehmigungstaste ** 3_allow_spreadsheet.png ** Sie werden nach dem Referenzblatt gefragt. Geben Sie daher die in ④ ** erstellte Tabelle an. 4_add_spreadsheet.png ** Drücken Sie "Zum Bericht hinzufügen" ** 5_confirm_spreadsheet.png ** Benennen Sie den Bericht um ** rename.png

Erstellen eines täglichen Stromverbrauchsdiagramms

Erstellen Sie ein Diagramm, um langfristige Änderungen anzuzeigen

** Klicken Sie auf Ressourcen → Hinzugefügte Datenquellen verwalten ** 7.png

** Klicken Sie auf "Bearbeiten" für die Zieldatenquelle ** 8.png

** Ändern Sie Datum und Uhrzeit in ein erkennbares Format ** (Das Datenportal hat ein striktes Format zur Erkennung von Datum und Uhrzeit.) Wenn Sie die richtigen Statistiken wie den Durchschnitt erhalten möchten: JJJJMMTT Wenn Sie den Messwert für jede Zeile anzeigen möchten: JJJJMMTThhmm 9.png

** Fügen Sie ein Feld hinzu (Feld für die Berechnung des Stromverbrauchs) ** 10.png

** Stellen Sie die Felder wie unten gezeigt ein (maximaler Stromverbrauch - minimaler Wert ≒ Stromverbrauch für den Tag) **

** Kehren Sie zum Hauptbildschirm zurück und klicken Sie auf das Diagramm, um zu einem Zeitreihendiagramm zu wechseln. ** 10.png

** Geben Sie die Dimension (horizontale Achse = Date_Master_Day) und den Index (vertikale Achse = Diff_CumlativeEnergy, die oben erstellt wurden) an. ** 13.png

** Ändern Sie den Indexnamen in "Täglicher Stromverbrauch (kWh)" ** 14.png

** Ändern, um fehlende Werte auszublenden ** 13.png

Erstellung eines Vergleichsdiagramms für den sofortigen Stromverbrauch und die Klimaanlage

Erstellen Sie ein Diagramm, in dem der alle 5 Minuten gemessene Stromverbrauch (Watt) mit dem Ein- und Ausschalten der Klimaanlage verglichen wird.

Erstellen eines Diagramms zum sofortigen Stromverbrauch

15.png

** Geben Sie die Abmessung (horizontale Achse = Date_Master) und den Index (vertikale Achse = Gerätename_Watt) an. ** 16.png

** Geben Sie den anzuzeigenden Datumsbereich an (in der folgenden Abbildung von 0:00 vor zwei Tagen bis 24:00 Uhr am Tag) ** 17.png

Hinzufügen von Informationen zum Ein- und Ausschalten der Klimaanlage

** Klicken Sie auf Ressourcen → Hinzugefügte Datenquellen verwalten ** 7.png

** Klicken Sie auf "Bearbeiten" für die Zieldatenquelle ** 8.png

** Erstellen Sie ein Feld "Aircon_On", das das Ein- und Ausschalten der Klimaanlage darstellt (siehe Abbildung unten). ** 18.png

** Fügen Sie "Aircon_On" zum selben Diagramm wie "Momentaner Stromverbrauch" hinzu ** 19.png

** Ändern Sie fehlende Werte, um sie linear zu vervollständigen ** 18.png

** Passen Sie die Anzeigefarbe des Diagramms an ** 20.png

Anpassen des gesamten Diagramms

Passen Sie das Gesamtlayout unter "Themen und Layouts" an. 21.png Fügen Sie ein Diagramm nach Ihren Wünschen hinzu → Zeigen Sie die erforderlichen Zahlen auf der Scorecard an. Es sieht besser aus

** Das ist es! ** **. watt.png

abschließend

Wie Sie sehen können, ist der Stromverbrauch der Klimaanlage enorm (beim Einschalten verdoppelt sich der Stromverbrauch mehr als ...) Darüber hinaus ist der Stromverbrauch unmittelbar nach dem Einschalten am höchsten, und es scheint, dass der Stromverbrauch allmählich abnimmt und wenn er auf ein bestimmtes Niveau abfällt, wird er krank.

** Informationen zum Ein- und Ausschalten von Fernsehgeräten und Glühbirnen ** können auch über die API abgerufen werden Nachdem wir diese hinzugefügt haben, schauen wir uns die Beziehung zum Stromverbrauch an.

Ich möchte "Wert" schaffen, indem ich die Stromrechnungen reduziere, ohne mit der Visualisierung zu enden! Ziel! ** Energiesparhaus! ** **.

Recommended Posts

Ich habe versucht, den Stromverbrauch meines Hauses mit Nature Remo E lite zu visualisieren
Ich habe versucht, den Text des Romans "Wetterkind" mit Word Cloud zu visualisieren
Ich habe versucht, die Tweets von JAWS DAYS 2017 mit Python + ELK einfach zu visualisieren
Ich habe versucht, die Spacha-Informationen von VTuber zu visualisieren
Ich habe versucht, die Eigenschaften der neuen Informationen über mit dem Corona-Virus infizierte Personen mit Wordcloud zu visualisieren
Ich habe versucht, die Laufdaten des Rennspiels (Assetto Corsa) mit Plotly zu visualisieren
Ich habe versucht, die Entropie des Bildes mit Python zu finden
Ich habe versucht, mit TensorFlow den Durchschnitt mehrerer Spalten zu ermitteln
[Python] Ich habe versucht, die folgende Beziehung von Twitter zu visualisieren
Ich habe versucht, die Bewässerung des Pflanzgefäßes mit Raspberry Pi zu automatisieren
Ich habe versucht, die Größe des logischen Volumes mit LVM zu erweitern
Ich möchte die Position meines Gesichts mit OpenCV überprüfen!
Ich habe versucht, die Effizienz der täglichen Arbeit mit Python zu verbessern
Ich habe versucht, den allgemeinen Zustand der VTuber-Kanalbetrachter zu visualisieren
Da die Aktie aufgrund des Einflusses des neuen Corona-Virus eingebrochen ist, habe ich versucht, die Performance meines Investment Trusts mit Python zu visualisieren.
Ich habe versucht, AutoEncoder mit TensorFlow zu visualisieren
[Python] Ich habe versucht, das Preisgeld von "ONE PIECE" über 100 Millionen Zeichen mit matplotlib zu visualisieren.
[Python] Ich habe versucht, die Nacht der Galaxienbahn mit WordCloud zu visualisieren!
Ich habe versucht, die Altersgruppe und die Ratenverteilung von Atcoder zu visualisieren
Ich habe versucht, die Genauigkeit meines eigenen neuronalen Netzwerks zu verbessern
Ich habe versucht, den Authentifizierungscode der Qiita-API mit Python abzurufen.
Ich möchte meine Gefühle mit den Texten von Mr. Children ausdrücken
Ich habe versucht, die Bewegungen von Wiire-Playern automatisch mit Software zu extrahieren
Ich habe versucht, die Negativität von Nono Morikubo zu analysieren. [Vergleiche mit Posipa]
Ich habe versucht, die Standardrolle neuer Mitarbeiter mit Python zu optimieren
Ich habe versucht, das Modell mit der Low-Code-Bibliothek für maschinelles Lernen "PyCaret" zu visualisieren.
Ich habe versucht, die Filminformationen der TMDb-API mit Python abzurufen
Ich habe versucht, alle Entscheidungsbäume des zufälligen Waldes mit SVG zu visualisieren
Ich habe versucht, das Verhalten des neuen Koronavirus mit dem SEIR-Modell vorherzusagen.
Da es der 20. Jahrestag der Gründung ist, habe ich versucht, die Texte von Parfüm mit Word Cloud zu visualisieren
Ich habe versucht, die Daten mit Zwietracht zu speichern
Ich habe versucht, die Trapezform des Bildes zu korrigieren
Ich habe versucht, die Texte von Hinatazaka 46 zu vektorisieren!
Die Geschichte von soracom_exporter (Ich habe versucht, SORACOM Air mit Prometheus zu überwachen)
Ich habe versucht, ein Modell mit dem Beispiel von Amazon SageMaker Autopilot zu erstellen
Ich habe versucht, die Literatur des neuen Corona-Virus mit Python automatisch an LINE zu senden
Ich habe versucht, die Sündenfunktion mit Chainer zu trainieren
Ich habe versucht, Funktionen mit SIFT von OpenCV zu extrahieren
Ich habe versucht, die Grundform von GPLVM zusammenzufassen
Ich habe versucht, eine CSV-Datei mit Python zu berühren
Ich habe versucht, Soma Cube mit Python zu lösen
Ich habe versucht, den negativen Teil von Meros zu löschen
Ich habe versucht, das Problem mit Python Vol.1 zu lösen
Ich habe versucht, die Stimmen der Sprecher zu klassifizieren
Ich habe versucht, die String-Operationen von Python zusammenzufassen
Ich habe versucht, mit dem Seq2Seq-Modell von TensorFlow so etwas wie einen Chatbot zu erstellen
Python-Übung 100 Schläge Ich habe versucht, den Entscheidungsbaum von Kapitel 5 mit graphviz zu visualisieren
Ich habe versucht, das Artikel-Update des Livedoor-Blogs mit Python und Selen zu automatisieren.
[Erste Datenwissenschaft ⑥] Ich habe versucht, den Marktpreis von Restaurants in Tokio zu visualisieren
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit dplyr von R und pandas von Python zu vergleichen
Beim 15. Offline-Echtzeitversuch habe ich versucht, das Problem des Schreibens mit Python zu lösen
Ich habe versucht, die Texte von GReeeen zu visualisieren, die ich in meiner Jugend verrückt gehört habe, aber nicht mehr gehört habe.
[Pferderennen] Ich habe versucht, die Stärke des Rennpferdes zu quantifizieren
Ich habe versucht, das Bild mit Python + OpenCV "gammakorrektur" zu machen
Ich habe versucht zu simulieren, wie sich die Infektion mit Python ausbreitet
Ich habe versucht, die Emotionen des gesamten Romans "Wetterkind" zu analysieren
Ich habe versucht, die Standortinformationen des Odakyu-Busses zu erhalten
Ich habe versucht, die Punktgruppendaten-DB der Präfektur Shizuoka mit Vue + Leaflet anzuzeigen