[PYTHON] J'ai essayé de visualiser la consommation électrique de ma maison avec Nature Remo E lite

introduction

Utilisation de "Nature Remo E lite" qui peut acquérir la quantité d'électricité utilisée à la maison en temps réel J'ai fait un tableau de bord qui visualise la consommation d'énergie watt.png En affichant l'état d'utilisation du climatiseur acquis par Nature Remo, ** Vous pouvez voir la relation entre la consommation d'énergie et la marche / arrêt du climatiseur d'un coup d'œil! ** ** J'ai le sentiment que nous avons fait un pas en avant vers la réalisation d'une maison économe en énergie.

IoT et compteur intelligent

Cela fait longtemps que le mot ** IoT ** est devenu un boom, Dans le même temps, la difficulté de créer de la valeur avec l'IoT se généralise et je sens que les yeux du monde sur l'IoT deviennent plus stricts.

La figure ci-dessous est la version 2019 du "Hype Cycle Diagram" annoncé par Gartner. L'IoT est entré dans une période de désillusion. 191031_gartner_hypecycle_2019.png

Surtout pour les produits IoT à usage domestique, à l'exception des haut-parleurs intelligents et des télécommandes intelligentes, qui sont prédominantes dans le monde, Je pense qu'il y a beaucoup de choses qui ne semblent pas avoir beaucoup de mérite même si elles sont rendues plus intelligentes.

Dans ces circonstances, le produit IoT que les entreprises d'électricité introduisent régulièrement est le ** Smart Meter **. Si nous pouvons visualiser et utiliser efficacement la consommation électrique, qui est un coût majeur pour les foyers et la société, Il est basé sur l'idée que la ** «valeur» ** peut être créée.

Qu'est-ce que Nature Remo E lite?

Le compteur intelligent ci-dessus transmet les données de consommation d'énergie par une norme sans fil appelée WiSUN, Ces données peuvent également être reçues et utilisées par des produits tiers (service B-root).

De ces produits tiers ** Dispositif de réception des données de consommation électrique ** développé par Nature, célèbre pour sa télécommande intelligente «Nature Remo»

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

Ce que tu peux faire

Avec Nature Remo E lite, vous pouvez:

・ Vérifiez la consommation d'énergie avec l'application

Vous pouvez vérifier la consommation électrique actuelle et un graphique historique simple avec l'application officielle. Screenshot_20200812-174424.png

・ Acquisition des données de consommation d'énergie par API

Les données de consommation d'énergie peuvent être gérées par programme à l'aide de l'API. Fondamentalement, il peut être obtenu auprès de API commune à Nature Remo.

GET /1/appliances

Avec la commande, vous pouvez obtenir les données de consommation d'énergie de Remo E lite ainsi que les données de l'appareil de Nature Remo.

Exemple d'exécution d'API

Tapez la commande suivante sous Linux ([Veuillez consulter ici pour savoir comment émettre des jetons d'accès](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:Jeton d'accès au porteur"

Le JSON suivant sera retourné

[
    {
    :
Autres informations sur l'appareil
    :
    },
    {
        "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": "Compteur intelligent",
        "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"
                }
            ]
        }
    },
    {
    :
Autres informations sur l'appareil
    :
    }
]

Informations sur les compteurs intelligents "smart_meter": Voir "val" dans la section "echonetlite_properties". Les deux sections ci-dessous sont particulièrement importantes.

normal_direction_cumulative_electric_energy: consommation électrique totale jusqu'à présent (unité: 0,01 kWh) Measured_instantaneous: Consommation électrique actuelle (unité: Watt)

Dans le cas du JSON ci-dessus, la consommation électrique totale est de 2942,63 kWh et la consommation électrique actuelle est de 464 watts.

** Cette fois, nous utiliserons cette API pour afficher la relation entre la consommation d'énergie et l'activation / désactivation du climatiseur dans un graphique comme indiqué dans l'image du haut **

Les choses nécessaires

** ・ Nature Remo E lite ** ** ・ Normal Nature Remo ** ‥ Requis pour obtenir des informations marche-arrêt pour les climatiseurs ** ・ Raspberry Pi ** (Raspberry Pi3 Model B est utilisé cette fois) ** ・ Environnement d'exécution Python ** (Python 3.7.3 prédéfini est utilisé cette fois) ** ・ Compte Google ** (requis pour utiliser la feuille de calcul et le portail de données)

procédure

Suivez les étapes ci-dessous pour créer un tableau de bord de consommation d'énergie.

** 1. Demander le service de route B à la compagnie d'électricité 2. Paramètres initiaux de Nature Remo E lite 3. Construire un système de journalisation avec Raspberry Pi 4. Création d'un tableau de bord de consommation électrique **

1. Demander un service de route B à la compagnie d'électricité

Afin d'acquérir les données du compteur intelligent, il est nécessaire de demander le service de route B à la compagnie d'électricité utilisée. (Même si vous utilisez un service comme au Denki pour la libéralisation de l'électricité, il semble que vous deviez vous adresser à une compagnie d'électricité locale comme TEPCO)

Postulez depuis la page d'accueil de la compagnie d'électricité

Dans mon cas, j'ai postulé à partir du site Web de Kansai Electric Power Group ci-dessous. https://www.kansai-td.co.jp/application/smart-meter/low-pressure/index.html

Pour les autres zones de la compagnie d'électricité, veuillez vous référer à ce qui suit https://chasuke.com/nremoe/

Lorsque j'ai postulé, j'ai reçu un appel téléphonique et j'ai dit qu'une construction simple (gratuite) était nécessaire, donc le flux consistait à ajuster le calendrier et ensuite à effectuer la construction.

La nécessité ou non de la construction dépend de l'état d'installation des compteurs intelligents de la maison. À partir de 2020, il semble qu'environ deux tiers des ménages du pays deviennent des compteurs intelligents. ・ Pour les ménages qui ne sont pas des compteurs intelligents, vous pouvez demander le remplacement avec priorité lors de la demande ci-dessus. ・ Même s'il s'agit d'un compteur intelligent, des travaux supplémentaires peuvent être nécessaires comme moi. Il semble.

B Réception de l'ID et du mot de passe du service racine

Lorsque l'application et la construction ci-dessus sont terminées, la compagnie d'électricité vous enverra l'ID et le mot de passe du service d'itinéraire B par courrier. Chez TEPCO, le mot de passe est envoyé par email, et la méthode d'envoi semble différer selon la zone (en tout cas, je pense que c'est soit email, soit mail).

2. Paramètres initiaux de Nature Remo E lite

Branchez le Nature Remo E lite dans la prise

Branchez le Nature Remo E lite dans la prise. Je sentais que le brancher dans une prise proche du standard fonctionnait souvent mieux lors de la synchronisation ultérieure. IMG_20200812_172047.jpg

Téléchargez l'application Nature Remo

Téléchargez l'application du site ci-dessous sur votre smartphone et installez-la. android iOS

Réglage initial

En gros, suivez les instructions de l'application pour procéder aux réglages initiaux, Si un identifiant et un mot de passe vous sont demandés en cours de route, entrez le contenu envoyé par la compagnie d'électricité.

Parfois, cela échoue lors de la synchronisation avec un compteur ou le WiFi, mais je Dans le cas de, cela fonctionnait souvent si j'essayais plusieurs fois.

3. Construire un système de journalisation avec Raspberry Pi

Le système d'enregistrement des données de capteur développé précédemment sera utilisé. Tout d'abord, veuillez lire le contenu de cet article (il est long, mais j'apprécierais que vous puissiez vous associer à moi)

Cette fois, afin de rendre le système ci-dessus compatible avec Nature Remo E lite Vous devez réécrire remo.py et capteurs_to_spreadsheet.py. Veuillez réécrire chacun comme suit. (Correspond à l'opération d'incorporation du JSON renvoyé dans [exemple d'exécution d'API] ci-dessus dans la cible de journalisation)

remo.py


import json
import requests
import glob
import pandas as pd

#Classe d'acquisition de données Remo
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

    #Extraire les données du capteur et les convertir au format dict
    def _decodeSensorData(self, rjson):
        for device in rjson:
            #Données Remo
            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

    #Extraire les données du climatiseur et de l'alimentation et les convertir au format dict
    def _decodeAirconPowerData(self, rjson):
        Value = {}
        for appliance in rjson:
            #Climatisation
            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']
            #Données de puissance du compteur intelligent
            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'])        
        #Si la valeur ne peut pas être obtenue, définissez-la sur Aucun.
        if len(Value) == 0:
            Value = None
        return Value

Les données de consommation d'énergie sont acquises par les méthodes ci-dessus get_aircon_power_data et _decodeAirconPowerData.

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

#Variables globales(Temps d'acquisition)
global masterdate

######Acquisition de valeurs pour le capteur d'environnement OMRON (type BAG)######
def getdata_omron_bag(device):
    #Appareil maximum lorsqu'aucune valeur n'est disponible.Réessayer de répéter l'analyse
    for i in range(device.Retry):
        #omron_Définit le délégué d'acquisition de la valeur du capteur d'env pour s'exécuter au moment du scan
        scanner = btle.Scanner().withDelegate(OmronBroadcastScanDelegate())
        #Scannez pour obtenir la valeur du capteur
        try:
            scanner.scan(device.Timeout)
        #Si vous obtenez une erreur lors de l'analyse, redémarrez l'adaptateur Bluetooth
        except:
            restart_hci0(device.DeviceName)
        #Terminer la boucle lorsque la valeur peut être obtenue
        if scanner.delegate.sensorValue is not None:
            break
        #Si la valeur ne peut pas être obtenue, écrivez-la dans le journal
        else:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, timeout{device.Timeout}]')
    
    #Si la valeur peut être obtenue, stockez les données POST dans dict
    if scanner.delegate.sensorValue is not None:
        #Données à 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
    #Si la valeur n'a pas pu être obtenue, enregistrez la sortie et redémarrez l'adaptateur Bluetooth
    else:
        logging.error(f'cannot get data [date{str(masterdate)}, device{device.DeviceName}, timeout{device.Timeout}]')
        restart_hci0(device.DeviceName)
        return None

######Acquisition de données du capteur d'environnement OMRON (type USB)######
def getdata_omron_usb(device):
    #Appareil maximum lorsqu'aucune valeur n'est disponible.Réessayer de répéter l'analyse
    for i in range(device.Retry):
        try:
            sensorValue = GetOmronConnectModeData().get_env_usb_data(device.MacAddress)
        #Sortie de journal si une erreur se produit
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}]')
            sensorValue = None
            continue
        else:
            break
    
    #Si la valeur peut être obtenue, stockez les données POST dans dict
    if sensorValue is not None:
        #Données à 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
    #Si la valeur n'a pas pu être obtenue, enregistrez la sortie et redémarrez l'adaptateur Bluetooth
    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-Acquisition de données TH1######
def getdata_ibsth1(device):
    #Appareil maximum lorsqu'aucune valeur n'est disponible.Réessayer de répéter l'analyse
    for i in range(device.Retry):
        try:
            sensorValue = GetIBSTH1Data().get_ibsth1_data(device.MacAddress, device.SensorType)
        #Sortie de journal si une erreur se produit
        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:
        #Données à POST
        data = {        
            'DeviceName': device.DeviceName,        
            'Date_Master': masterdate,
            'Date': datetime.today(),
            'Temperature': sensorValue['Temperature'],
            'Humidity': sensorValue['Humidity']
        }
        return data
    #Si la valeur n'a pas pu être obtenue, enregistrez la sortie et redémarrez l'adaptateur Bluetooth
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}]')
        restart_hci0(device.DeviceName)
        return None

######Acquisition des données du thermo-hygromètre SwitchBot######
def getdata_switchbot_thermo(device):
    #Appareil maximum lorsqu'aucune valeur n'est disponible.Réessayer de répéter l'analyse
    for i in range(device.Retry):
        #Définir le délégué d'acquisition de la valeur du capteur Switchbot
        scanner = btle.Scanner().withDelegate(SwitchbotScanDelegate(str.lower(device.MacAddress)))
        #Scannez pour obtenir la valeur du capteur
        try:
            scanner.scan(device.Timeout)
        #Si vous obtenez une erreur lors de l'analyse, redémarrez l'adaptateur Bluetooth
        except:
            restart_hci0(device.DeviceName)
        #Terminer la boucle lorsque la valeur peut être obtenue
        if scanner.delegate.sensorValue is not None:
            break
        #Si la valeur ne peut pas être obtenue, écrivez-la dans le journal
        else:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, timeout{device.Timeout}]')
    
    #Si la valeur peut être obtenue, stockez les données POST dans dict
    if scanner.delegate.sensorValue is not None:
        #Données à 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
    #Sinon, sortez le journal et redémarrez l'adaptateur Bluetooth
    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

######Acquisition de données Nature Remo######
def getdata_remo(device, csvpath):
    #Appareil maximum lorsque la valeur des données du capteur n'est pas disponible.Réessayer de répéter l'analyse
    for i in range(device.Retry):
        try:
            sensorValue = GetRemoData().get_sensor_data(device.Token, device.API_URL)
        #Sortie de journal si une erreur se produit
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, sensor]')
            sensorValue = None
            continue
        else:
            break
    #Appareil maximum lorsque les valeurs des données de climatisation et de puissance ne sont pas disponibles.Réessayer de répéter l'analyse
    for i in range(device.Retry):
        try:
            airconPowerValue = GetRemoData().get_aircon_power_data(device.Token, device.API_URL)
        #Sortie de journal si une erreur se produit
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}, aircon]')
            sensorValue = None
            continue
        else:
            break
        
    #Si la valeur peut être obtenue, stockez les données POST dans dict
    if sensorValue is not None:
        #Données du capteur
        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}')
        }
        #Climatiseur et données d'alimentation
        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'
            #Puissance
            if 'CumulativeEnergy' in airconPowerValue:
                data['CumulativeEnergy'] = float(airconPowerValue['CumulativeEnergy'])
            if 'Watt' in airconPowerValue:
                data['Watt'] = int(airconPowerValue['Watt'])
        return data
    #S'il ne peut pas être obtenu, enregistrez la sortie (comme c'est via WiFi, l'adaptateur Bluetooth ne sera pas redémarré)
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}]')
        return None

######Sortie CSV des données######
def output_csv(data, csvpath):
    dvname = data['DeviceName']
    monthstr = masterdate.strftime('%Y%m')
    #Nom du dossier de destination de sortie
    outdir = f'{csvpath}/{dvname}/{masterdate.year}'
    #Lorsque le dossier de destination de sortie n'existe pas, créez-en un nouveau
    os.makedirs(outdir, exist_ok=True)
    #Chemin du fichier de sortie
    outpath = f'{outdir}/{dvname}_{monthstr}.csv'
    
    #Créer un nouveau fichier de sortie lorsqu'il n'existe pas
    if not os.path.exists(outpath):        
        with open(outpath, 'w') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writeheader()
            writer.writerow(data)
    #Ajouter une ligne lorsque le fichier de sortie existe
    else:
        with open(outpath, 'a') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writerow(data)

######Processus de téléchargement sur la feuille de calcul Google######
def output_spreadsheet(all_values_dict_str):
    #URL de l'API
    url = 'URL de l'API GAS répertoriée ici'
    #POST des données vers l'API
    response = requests.post(url, json=all_values_dict_str)
    print(response.text)

######Redémarrage de l'adaptateur Bluetooth######
def restart_hci0(devicename):
    passwd = 'Entrez le mot de passe RaspberryPi'#Ajouter une dissimulation si nécessaire
    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}]')


######Principale######
if __name__ == '__main__':
    #Obtenir l'heure de début
    startdate = datetime.today()
    #Arrondissez l'heure de début en minutes
    masterdate = startdate.replace(second=0, microsecond=0)   
    if startdate.second >= 30:
        masterdate += timedelta(minutes=1)

    #Lire le fichier de configuration et la liste des appareils
    cfg = configparser.ConfigParser()
    cfg.read('./config.ini', encoding='utf-8')
    df_devicelist = pd.read_csv('./DeviceList.csv')
    #Nombre total de capteurs et acquisition de données réussie
    sensor_num = len(df_devicelist)
    success_num = 0

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

    #Dict pour conserver toutes les données acquises
    all_values_dict = None
    #Version chaîne de caractères du dict ci-dessus (pour GAS Post, car le type datetime ne peut pas être converti en JSON)
    all_values_dict_str = None

    #Heure de début de l'acquisition des données
    scan_start_date = datetime.today()

    ######Acquisition de données pour chaque appareil######
    for device in df_devicelist.itertuples():
        #Type de sac du capteur d'environnement Omron (connexion BroadCast)
        if device.SensorType in ['Omron_BAG_EP','Omron_BAG_IM']:
            data = getdata_omron_bag(device)
        #Capteur d'environnement Omron Type USB (connexion en mode Connect)
        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)
        #Thermo-hygromètre SwitchBot
        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)
        #Autre que ceux ci-dessus
        else:
            data = None        

        #Lorsque des données existent, ajoutez-les à Dict pour contenir toutes les données et générer le CSV
        if data is not None:
            #all_values_Créer un nouveau dictionnaire lorsque dict est None
            if all_values_dict is None:
                #all_values_Créer un dict (Parce que c'est le premier, Date_Maître et date_ScanStart est également ajouté)
                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']))
                #Convertir les données en chaîne et tout_values_dict_créer str(Date parce que c'est le premier_ScanStart ajouté)
                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_Ajouter au dictionnaire existant lorsque dict n'est pas None
            else:
                #all_values_Ajouté à dict (Date car ce n'est pas le premier_Maître exclu)
                all_values_dict.update(dict([(data['DeviceName']+'_'+k, v) for k,v in data.items() if k != 'Date_Master']))
                #all_values_dict_Ajouter à str
                data_str = dict([(k, str(v)) for k,v in data.items()])
                all_values_dict_str[data_str['DeviceName']] = data_str

            #Sortie CSV
            output_csv(data_str, cfg['Path']['CSVOutput'])
            #Numéro de réussite plus
            success_num+=1

    ######Processus de téléchargement sur la feuille de calcul Google######
    output_spreadsheet(all_values_dict_str)

    #Sortie du journal de la fin du traitement
    logging.info(f'[masterdate{str(masterdate)} startdate{str(startdate)} enddate{str(datetime.today())} success{str(success_num)}/{str(sensor_num)}]')

Outre la possibilité d'acquérir des données Remo E lite, nous avons apporté quelques améliorations, mais Je pense que c'est un niveau dont vous n'avez pas à vous soucier en fonctionnement réel.

De plus, si le fichier de configuration DeviceList.csv contient NatureRemo (API_URL et Token doivent être saisis), Aucun nouvel ajout n'est requis pour Remo E lite.

Lorsque vous commencez à vous connecter avec cron, comme indiqué dans le cadre rouge ci-dessous, Nom de l'appareil_CumulativeEnergy: consommation électrique totale (unité: kWh) Nom de l'appareil_Watt: Consommation électrique actuelle (unité: Watt) Deux types de champs sont ajoutés. spreadsheet_remoelite.png

Vous pouvez voir que la consommation d'énergie augmente à la fois lorsque le climatiseur est allumé. Dans le chapitre suivant, illustrons cette situation.

4. Création d'un tableau de bord de consommation d'énergie

Google Data Portal est un tableau de bord qui peut être modifié et affiché sur le cloud. Utilisez cet outil pour créer un tableau de bord qui montre la relation entre la consommation d'énergie et la marche / arrêt du climatiseur.

Créer un nouveau rapport

1_dataportal.png ** Spécifiez une feuille de calcul Google comme destination de la connexion de données ** 2_connect_spreadsheet.png ** Si vous êtes invité à approuver, appuyez sur le bouton d'approbation ** 3_allow_spreadsheet.png ** Il vous sera demandé la feuille de référence, alors spécifiez la feuille de calcul créée en ④ ** 4_add_spreadsheet.png ** Appuyez sur "Ajouter au rapport" ** 5_confirm_spreadsheet.png ** Renommer le rapport ** rename.png

Création d'un graphique de consommation d'énergie quotidienne

Créez un graphique pour voir les changements à long terme

** Cliquez sur Ressources → Gérer les sources de données ajoutées ** 7.png

** Cliquez sur "Modifier" pour la source de données cible ** 8.png

** Changez la date et l'heure dans un format reconnaissable ** (Le portail de données a un format strict de reconnaissance de la date et de l'heure) Si vous souhaitez obtenir les statistiques correctes telles que la moyenne: AAAAMMJJ Si vous souhaitez afficher la valeur mesurée pour chaque ligne: AAAAMMJJhhmm 9.png

** Ajouter un champ (champ pour le calcul de la consommation d'énergie) ** 10.png

** Réglez les champs comme indiqué ci-dessous (consommation électrique maximale-valeur minimale ≒ consommation électrique pour la journée) **

** Revenez à l'écran principal et cliquez sur le graphique pour passer à un graphique chronologique ** 10.png

** Spécifiez la dimension (axe horizontal = Date_Master_Day) et l'index (axe vertical = Diff_CumlativeEnergy créé ci-dessus) ** 13.png

** Remplacez le nom de l'index par "Consommation d'énergie quotidienne (kWh)" ** 14.png

** Modifier pour masquer les valeurs manquantes ** 13.png

Création d'un graphique de comparaison de la consommation d'énergie instantanée et du climatiseur

Créez un graphique comparant la consommation d'énergie (Watt) mesurée toutes les 5 minutes avec le climatiseur marche-arrêt.

Création d'un graphique de consommation d'énergie instantanée

15.png

** Spécifiez la dimension (axe horizontal = Date_Master) et l'index (axe vertical = nom de l'appareil_Watt) ** 16.png

** Spécifiez la plage de dates à afficher (dans la figure ci-dessous, de 0:00 il y a deux jours à 24:00 le jour même) ** 17.png

Ajout d'informations marche / arrêt du climatiseur

** Cliquez sur Ressources → Gérer les sources de données ajoutées ** 7.png

** Cliquez sur "Modifier" pour la source de données cible ** 8.png

** Créez un champ "Aircon_On" qui représente Marche-Arrêt du climatiseur comme indiqué dans la figure ci-dessous ** 18.png

** Ajoutez «Aircon_On» au même graphique que la consommation d'énergie instantanée ** 19.png

** Modifier les valeurs manquantes pour terminer linéairement ** 18.png

** Ajustez la couleur d'affichage du graphique ** 20.png

Ajuster l'ensemble du graphique

Ajustez la disposition générale à partir de "Thèmes et mises en page" 21.png Ajouter un graphique à votre goût → Afficher les nombres souhaités sur la carte de score, Ça a l'air mieux

** C'est tout! ** ** watt.png

en conclusion

Comme vous pouvez le constater, la consommation électrique du climatiseur est énorme (lorsqu'il est allumé, la consommation électrique fait plus que doubler ...) De plus, la consommation d'énergie est la plus élevée immédiatement après sa mise sous tension, et il semble que la consommation d'énergie diminue progressivement et lorsqu'elle tombe à un certain niveau, elle tombe malade.

** Les informations ON-OFF du téléviseur et de l'ampoule ** peuvent également être obtenues avec l'API, donc Après avoir ajouté ces derniers, examinons la relation avec la consommation d'énergie.

Je veux créer de la «valeur» en réduisant les factures d'électricité sans finir par la visualisation! Objectif! ** Maison à économie d'énergie! ** **

Recommended Posts

J'ai essayé de visualiser la consommation électrique de ma maison avec Nature Remo E lite
J'ai essayé de visualiser le texte du roman "Weather Child" avec Word Cloud
J'ai essayé de visualiser facilement les tweets de JAWS DAYS 2017 avec Python + ELK
J'ai essayé de visualiser les informations spacha de VTuber
J'ai essayé de visualiser les caractéristiques des nouvelles informations sur les personnes infectées par le virus corona avec wordcloud
J'ai essayé de visualiser les données de course du jeu de course (Assetto Corsa) avec Plotly
J'ai essayé de trouver l'entropie de l'image avec python
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
[Python] J'ai essayé de visualiser la relation de suivi de Twitter
J'ai essayé d'automatiser l'arrosage du pot avec Raspberry Pi
J'ai essayé d'agrandir la taille du volume logique avec LVM
Je veux vérifier la position de mon visage avec OpenCV!
J'ai essayé d'améliorer l'efficacité du travail quotidien avec Python
J'ai essayé de visualiser la condition commune des téléspectateurs de la chaîne VTuber
Depuis que le stock a plongé en raison de l'influence du nouveau virus corona, j'ai essayé de visualiser les performances de ma fiducie d'investissement avec Python.
J'ai essayé de visualiser AutoEncoder avec TensorFlow
[Python] J'ai essayé de visualiser le prix en argent de "ONE PIECE" plus de 100 millions de caractères avec matplotlib.
[Python] J'ai essayé de visualiser la nuit du chemin de fer de la galaxie avec WordCloud!
J'ai essayé de visualiser la tranche d'âge et la distribution des taux d'Atcoder
J'ai essayé d'améliorer la précision de mon propre réseau neuronal
J'ai essayé d'obtenir le code d'authentification de l'API Qiita avec Python.
Je veux exprimer mes sentiments avec les paroles de Mr. Children
J'ai essayé d'extraire automatiquement les mouvements des joueurs Wiire avec un logiciel
J'ai essayé d'analyser la négativité de Nono Morikubo. [Comparer avec Posipa]
J'ai essayé de rationaliser le rôle standard des nouveaux employés avec Python
J'ai essayé de visualiser le modèle avec la bibliothèque d'apprentissage automatique low-code "PyCaret"
J'ai essayé d'obtenir les informations sur le film de l'API TMDb avec Python
J'ai essayé de visualiser tous les arbres de décision de la forêt aléatoire avec SVG
J'ai essayé de prédire le comportement du nouveau virus corona avec le modèle SEIR.
Comme c'est le 20e anniversaire de la formation, j'ai essayé de visualiser les paroles de Parfum avec Word Cloud
J'ai essayé de sauvegarder les données avec discorde
J'ai essayé de corriger la forme trapézoïdale de l'image
J'ai essayé de vectoriser les paroles de Hinatazaka 46!
L'histoire de la fabrication de soracom_exporter (j'ai essayé de surveiller SORACOM Air avec Prometheus)
J'ai essayé de créer un modèle avec l'exemple d'Amazon SageMaker Autopilot
J'ai essayé d'envoyer automatiquement la littérature du nouveau virus corona à LINE avec Python
J'ai essayé d'entraîner la fonction péché avec chainer
J'ai essayé d'extraire des fonctionnalités avec SIFT d'OpenCV
J'ai essayé de résumer la forme de base de GPLVM
J'ai essayé de toucher un fichier CSV avec Python
J'ai essayé de résoudre Soma Cube avec python
J'ai essayé d'effacer la partie négative de Meros
J'ai essayé de résoudre le problème avec Python Vol.1
J'ai essayé de classer les voix des acteurs de la voix
J'ai essayé de résumer les opérations de chaîne de Python
J'ai essayé de faire quelque chose comme un chatbot avec le modèle Seq2Seq de TensorFlow
Python pratique 100 coups J'ai essayé de visualiser l'arbre de décision du chapitre 5 en utilisant graphviz
J'ai essayé d'automatiser la mise à jour de l'article du blog Livedoor avec Python et sélénium.
[First data science ⑥] J'ai essayé de visualiser le prix du marché des restaurants à Tokyo
J'ai essayé de comparer la vitesse de traitement avec dplyr de R et pandas de Python
Le 15e temps réel hors ligne, j'ai essayé de résoudre le problème de l'écriture avec python
J'ai essayé de visualiser les paroles de GReeeen, que j'écoutais de façon folle dans ma jeunesse mais que je ne l'écoutais plus.
[Courses de chevaux] J'ai essayé de quantifier la force du cheval de course
J'ai essayé la "correction gamma" de l'image avec Python + OpenCV
J'ai essayé de simuler la propagation de l'infection avec Python
J'ai essayé d'analyser les émotions de tout le roman "Weather Child" ☔️
J'ai essayé d'obtenir les informations de localisation du bus Odakyu
J'ai essayé d'afficher les données du groupe de points DB de la préfecture de Shizuoka avec Vue + Leaflet