IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

ESP32 + CherryPy [Arduino ESP32]


Sujet :

Arduino

  1. #21
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 286
    Billets dans le blog
    48
    Par défaut
    Citation Envoyé par cobra38 Voir le message
    hypothèse
    un PC => 192.168.1.171
    Si ton PC est à l'adresse IP 192.168.1.171, alors ton serveur CherryPy est à cette adresse puisqu'il est sur le PC (sur le port 8080).

    Donc dans ta config, il faut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [global]
    server.socket_host = "192.168.1.171"
    server.socket_port = 8080
    ...
    Ici, server.socket_host n'est pas l'adresse IP du serveur au sens "son "identité", mais l'interface réseau sur lequel le serveur est à l'écoute. Alors on y met quand même l'adresse IP du serveur, mais ce paramètre indique que le serveur écoute les connexions entrantes uniquement dans le réseau local, c'est-à-dire des appareils en 192.168.1.x.

    Comme ton esp32 est sur le même réseau local en 192.168.1.110, le serveur va accepter sa requête.


    Si tu mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [global]
    server.socket_host = "127.0.0.1"
    server.socket_port = 8080
    ...
    Ton serveur est toujours sur 192.168.1.171:8080, mais tu indiques que ton serveur n'acceptera que les requêtes provenant de la même interface locale (localhost). Cela veut dire que ton esp32 ne pourra pas s'y connecter même s'il est sur le même réseau local. Le serveur n'accepte que les requêtes en provenance du PC lui-même. Evidemment, cette configuration ne t'intéresse pas.

    Enfin, si tu mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [global]
    server.socket_host = "0.0.0.0"
    server.socket_port = 8080
    ...
    Ton serveur est toujours sur 192.168.1.171:8080, mais tu indiques que ton serveur accepte toutes les requêtes, toutes les portes sont ouvertes. Si tu as configuré ta box pour mettre ton serveur sur Internet, tu peux mettre ton esp32 à l'autre bout du monde et le serveur l'acceptera.
    Maintenant que j'y pense, si l'adresse IP du PC n'est pas fixe, tu peux mettre cette configuration.

    Dans tous les cas, 192.168.1.171:8080 est l'adresse IP de ton serveur. Le paramètre server.socket_host indique à quelle(s) porte(s) le serveur va coller son oreille pour les requêtes entrantes.

    Avec server.socket_host, tu poses la question :
    Est-ce que le serveur écoute à toutes les portes ( server.socket_host = "0.0.0.0"), uniquement celle du réseau local (server.socket_host = "192.168.1.171"), ou uniquement celle de l'hôte local (server.socket_host = "127.0.0.1") ?

  2. #22
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    merci f-leb

    pour ce cours PC <-> SERVEUR , je pense que j'en avais vraiment besoin, j'y vois un peu plus clair maintenant
    j'avais complétement zappé le PC dans cette histoire !

    néanmoins , j'en suis à la case départ car lorsque je sollicite CherryPy avec : py index.py
    celui ci ne répond pas alors qu'avec les exemples ou tutos cela fonctionne
    je soupçonne fortement l'erreur de lecture du fichier index.py avec la dernière version de CherryPy
    en effet lorsque sous shell , je lance le prog celui-ci semble bloqué comme en attente ...( je n'ai d'ailleurs plus la main )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    C:\Users\Utilisateur\Documents\essai>py index.py
    [12/Sep/2025:08:14:25]  SERVER starting at C:\Users\Utilisateur\Documents\essai
    [12/Sep/2025:08:14:25] ENGINE Serving on http://192.168.1.171:8080
    code index.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import sys, os, locale, logging
    from datetime import datetime
    from dateutil import parser
    import cherrypy
    from cherrypy.lib.static import serve_file 
    from template import Template
     
    logger = logging.getLogger('index')
     
    current_dir = os.path.realpath(os.path.curdir)
     
    gpioSerie = """
            {
              name: '%s',
              type: 'spline',
              data: [%s],
            },
    		"""
     
    adcSerie = """
            {
              name: '%s',
              type: 'spline',
              data: [%s],
              tooltip: {
                  valueSuffix: 'V'
              },
            },
    		"""
     
    class HomePage(object):
     
    	def __init__(self):
    		logger.setLevel(logging.DEBUG)
    		ch = logging.StreamHandler()
    		ch.setLevel(logging.DEBUG)
    		formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    		ch.setFormatter(formatter)
    		logger.addHandler(ch)
    		self.data = {}
    		self.xLabel = 's'
     
    	def load(self, fileName):
    		f = open(fileName, 'r')
    		return f.read()
     
    	def getXData(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		for dt in k:
    			if len(data) != 0:
    				data += ', '
    			data += "Date.UTC(%s, %s, %s, %s, %s, %s, %s)" % (dt.year, dt.month-1, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond/1000)
     
    		return data
     
    	def hasPowerData(self):
    		k = self.data.keys()
    		k.sort()
    		if len(k) and 'CURRENT' in self.data[k[0]]:
    			return True
    		return False
     
    	def hasGpioData(self):
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			gpioList = self.data[k[0]]
    			for gpio in gpioList:
    				serie = ''
    				if gpio.startswith('GPIO'):
    					return True
    		return False
     
    	def hasAdcData(self):
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			adcList = self.data[k[0]]
    			for adc in adcList:
    				serie = ''
    				if adc.startswith('ADC'):
    					return True
    		return False
     
    	def getCurrentData(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k) and 'CURRENT' in self.data[k[0]]:
    			for entry in k:
    				if len(data) != 0:
    					data += ', '
    				data += self.data[entry]['CURRENT']
    		return data
     
    	def getVoltageData(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k) and 'VOLTAGE' in self.data[k[0]]:
    			for entry in k:
    				if len(data) != 0:
    					data += ', '
    				data += self.data[entry]['VOLTAGE']
    		return data
     
    	def getGpioSeries(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			gpioList = self.data[k[0]]
    			for gpio in gpioList:
    				serie = ''
    				if gpio.startswith('GPIO'):
    					id = gpio
    					if not gpio[4:].isdigit():
    						id = gpio[5:]
    					for entry in k:
    						if len(serie) != 0:
    							serie += ', '
    						serie += self.data[entry][gpio]
    					data += gpioSerie % (id, serie)
    		return data
     
    	def getAdcSeries(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			adcList = self.data[k[0]]
    			for adc in adcList:
    				serie = ''
    				if adc.startswith('ADC'):
    					id = adc
    					if not adc[3:].isdigit():
    						id = adc[4:]
    					for entry in k:
    						if len(serie) != 0:
    							serie += ', '
    						serie += self.data[entry][adc]
    					data += adcSerie % (id, serie)
    		return data
     
    	@cherrypy.expose
    	def favicon_ico(self):
    		current_dir = os.path.realpath(os.path.curdir)
    		return serve_file(current_dir + '/favicon.ico')
     
    	@cherrypy.expose
    	def index(self):
    		tmpl = self.load('index.html')
    		nameSpace = {'XDATA': self.getXData(),
    					   	'XLABEL': self.xLabel,
    					   	'CURRENT_DATA': self.getCurrentData(),
    						'VOLTAGE_DATA': self.getVoltageData(),
    						'GPIO_SERIES': self.getGpioSeries(),
    						'ADC_SERIES': self.getAdcSeries(),
    						'DISPLAY_POWER': "block" if self.hasPowerData() else "none",
    						'DISPLAY_GPIO': "block" if self.hasGpioData() else "none",
    						'DISPLAY_ADC': "block" if self.hasAdcData() else "none"
    					}
    		return Template(tmpl, searchList=[nameSpace]).respond()
     
    	@cherrypy.expose
    	def clear(self):
    		self.data = {}
    		raise cherrypy.HTTPRedirect("/") 
     
    	@cherrypy.expose
    	def export(self, filename='log.csv'):
    		k = self.data.keys()
    		k.sort()
    		data = 'TIME'
    		if len(k):
    			f = open(filename, 'w')
    			columns = self.data[k[0]].keys()
    			columns.sort()
    			for col in columns:
    				data += ';'
    				data += col
    			data += '\n'
    			f.write(data)
    			data = ''
    			for entry in k:
    				data += str(entry)
    				for col in columns:
    					data += ';'
    					data += self.data[entry][col]
    				data += '\n'
    				f.write(data)
    				data = ''
    			f.close()
    			path = os.path.join(os.getcwd(), filename)
    			return serve_file(path, "application/x-download", "attachment", os.path.basename(path))
     
    	@cherrypy.expose
    	def log(self, **kwargs):
    		logger.debug('log %s' % kwargs)
    		if "dt" in kwargs:
    			dt = parser.parse(kwargs["dt"])
    		else:
    			dt = datetime.now()
    		self.data[dt] = {}
    		for arg in kwargs.keys():
    			self.data[dt][arg] = kwargs[arg]
    		tmpl = self.load('index.html')
    		return "OK"
     
    cherrypy.root = HomePage()
     
    if __name__ == '__main__':
    	cherrypy.config.update('web-power-monitor.conf')
    	cherrypy.log('SERVER starting at %s' % os.getcwd())
    	cherrypy.server.start()

  3. #23
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 286
    Billets dans le blog
    48
    Par défaut
    Le serveur est opérationnel a priori, il doit être à l'écoute en attente d'une requête de l'esp32.

    Que se passe-t-il dans le navigateur à l'URL http://192.168.1.171:8080 ?

    Peut-être aussi que l'esp32 n'envoie pas de requêtes, ou pas au bon endroit. Quel code tu as dans l'esp32 ?

  4. #24
    Membre Expert
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 595
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 595
    Par défaut
    donc tu dis avoir 3 éléments:
    - carte arduino ESP32 (IP1)
    - "serveur" (IP2)
    - PC (IP3)

    sur l'arduino tu dois indiquer l'adresse du serveur IP2 dans le champs Host
    sur le serveur, tu laisses le 0.0.0.0 dans le fichier conf, et tu lances le CherryPy (qui joue le rôle de serveur)
    sur le PC, tu ouvres ton navigateur en mettant l'adresse IP2 (donc du serveur) suivi du port configuré

    si serveur et pc sont identiques (ou que tu veux consulter depuis le serveur), tu peux saisir dans le navigateur 127.0.0.1 ou localhost suivi du port

  5. #25
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    voici le code ESP32

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
     
    #include <WiFi.h>
    #include <WiFiClient.h>
    #include <WebServer.h>
    #include <ESPmDNS.h>
    #include <SPIFFS.h>
    #include <INA226.h>
     
    #define MAX_GPIO          40
    #define VREF              0.975
    #define ATTENUATION       3.6
     
    #define INA226_I2CADDR            0x40
    #define INA226_OHM                0.105  // ohm
    #define INA226_AMP                0.8
    #define INA226_OFFSET             0.000   // amps
     
    INA226 ina226;
     
    const char *ssid = "xxxxxxx";
    const char *password = "xxxxxxxx";
     
    char hostName[20] = "192.168.1.171";  <================================
    int port;
    int started;
    int powerMonitor;
    int gpioMonitor[MAX_GPIO];
    String gpioAlias[MAX_GPIO];
    int adcMonitor[MAX_GPIO];
    float adcDivider[MAX_GPIO];
    unsigned long period;
     
    WebServer server(80);
    WiFiClient client;
     
    const int led = 13;
     
    void checkConfig()
    {
      Serial.print("Mode:                  ");
      switch (ina226.getMode())
      {
        case INA226_MODE_POWER_DOWN:      Serial.println("Power-Down"); break;
        case INA226_MODE_SHUNT_TRIG:      Serial.println("Shunt Voltage, Triggered"); break;
        case INA226_MODE_BUS_TRIG:        Serial.println("Bus Voltage, Triggered"); break;
        case INA226_MODE_SHUNT_BUS_TRIG:  Serial.println("Shunt and Bus, Triggered"); break;
        case INA226_MODE_ADC_OFF:         Serial.println("ADC Off"); break;
        case INA226_MODE_SHUNT_CONT:      Serial.println("Shunt Voltage, Continuous"); break;
        case INA226_MODE_BUS_CONT:        Serial.println("Bus Voltage, Continuous"); break;
        case INA226_MODE_SHUNT_BUS_CONT:  Serial.println("Shunt and Bus, Continuous"); break;
        default: Serial.println("unknown");
      }
     
      Serial.print("Samples average:       ");
      switch (ina226.getAverages())
      {
        case INA226_AVERAGES_1:           Serial.println("1 sample"); break;
        case INA226_AVERAGES_4:           Serial.println("4 samples"); break;
        case INA226_AVERAGES_16:          Serial.println("16 samples"); break;
        case INA226_AVERAGES_64:          Serial.println("64 samples"); break;
        case INA226_AVERAGES_128:         Serial.println("128 samples"); break;
        case INA226_AVERAGES_256:         Serial.println("256 samples"); break;
        case INA226_AVERAGES_512:         Serial.println("512 samples"); break;
        case INA226_AVERAGES_1024:        Serial.println("1024 samples"); break;
        default: Serial.println("unknown");
      }
     
      Serial.print("Bus conversion time:   ");
      switch (ina226.getBusConversionTime())
      {
        case INA226_BUS_CONV_TIME_140US:  Serial.println("140uS"); break;
        case INA226_BUS_CONV_TIME_204US:  Serial.println("204uS"); break;
        case INA226_BUS_CONV_TIME_332US:  Serial.println("332uS"); break;
        case INA226_BUS_CONV_TIME_588US:  Serial.println("558uS"); break;
        case INA226_BUS_CONV_TIME_1100US: Serial.println("1.100ms"); break;
        case INA226_BUS_CONV_TIME_2116US: Serial.println("2.116ms"); break;
        case INA226_BUS_CONV_TIME_4156US: Serial.println("4.156ms"); break;
        case INA226_BUS_CONV_TIME_8244US: Serial.println("8.244ms"); break;
        default: Serial.println("unknown");
      }
     
      Serial.print("Shunt conversion time: ");
      switch (ina226.getShuntConversionTime())
      {
        case INA226_SHUNT_CONV_TIME_140US:  Serial.println("140uS"); break;
        case INA226_SHUNT_CONV_TIME_204US:  Serial.println("204uS"); break;
        case INA226_SHUNT_CONV_TIME_332US:  Serial.println("332uS"); break;
        case INA226_SHUNT_CONV_TIME_588US:  Serial.println("558uS"); break;
        case INA226_SHUNT_CONV_TIME_1100US: Serial.println("1.100ms"); break;
        case INA226_SHUNT_CONV_TIME_2116US: Serial.println("2.116ms"); break;
        case INA226_SHUNT_CONV_TIME_4156US: Serial.println("4.156ms"); break;
        case INA226_SHUNT_CONV_TIME_8244US: Serial.println("8.244ms"); break;
        default: Serial.println("unknown");
      }
     
      Serial.print("Max possible current:  ");
      Serial.print(ina226.getMaxPossibleCurrent());
      Serial.println(" A");
     
      Serial.print("Max current:           ");
      Serial.print(ina226.getMaxCurrent());
      Serial.println(" A");
     
      Serial.print("Max shunt voltage:     ");
      Serial.print(ina226.getMaxShuntVoltage());
      Serial.println(" V");
     
      Serial.print("Max power:             ");
      Serial.print(ina226.getMaxPower());
      Serial.println(" W");
    }
     
    void mount(void)
    {                                                                                                        
      int count;
      size_t total = 0, used = 0;
      struct dirent *ent;
     
      if (!SPIFFS.begin(true)) {
        printf("SPIFFS mount failed\n");
        return;
      }
      printf("\nSPIFFS mounted\n");
      printf("%ld / %ld bytes used\n", SPIFFS.usedBytes(), SPIFFS.totalBytes());
      File dir = SPIFFS.open("/");
      if (!dir) {
        printf("error opening /\n");
        return;
      }
      File file = dir.openNextFile();
      while (file) {
        printf("%s: %d bytes\n", file.name(), file.size());
        file = dir.openNextFile();
      }
      dir.close();
    }
     
    int hasArg(String &name)
    {
      for (int i = 0; i < server.args(); i++) {
        if (server.argName(i) == name) {
          return i;
        }
      }
      return -1;
    }
     
    void handleRoot()
    {
      Serial.println("handleRoot");
      String buf;
     
      started = false;
      File file = SPIFFS.open("/index.html");
      if (!file) {
        Serial.println("file not found");
        server.send(200, "text/plain", "index.html not found");
        return;
      }
      while (file.available()) {
        buf += file.readStringUntil('\n');
        buf += '\n';
      }
      Serial.println(buf);
      file.close();
      server.send(200, "text/html", buf);
    }
     
    void handleMonitor()
    {
      int looking = false;
     
      Serial.println("handleMonitor");
      String buf = "<!DOCTYPE HTML><html>\n<head>"
                   "  <style>"
                   "    body {"
                   "      min-width: 310px;"
                   "      max-width: 800px;"
                   "      height: 400px;"
                   "      margin: 0 auto;"
                   "    }"
                   "    h2 {"
                   "      font-family: Arial;"
                   "      font-size: 2.5;"
                   "      text-align: center;"
                   "    }"
                   "  </style>"
                   "</head>"
                   "<body>"
                   "  <h2>WEB Power Monitor RUNNING</h2>";
     
      started = true;
      powerMonitor = false;
      memset(gpioMonitor, 0, sizeof(gpioMonitor));
      memset(gpioAlias, 0, sizeof(gpioAlias));
      memset(adcMonitor, 0, sizeof(adcMonitor));
      for (int i = 0; i < server.args(); i++) {
        Serial.print(server.argName(i) + " ");
        Serial.println(server.arg(i));
        if (server.argName(i) == "host") {
          server.arg(i).toCharArray(hostName, 20);
          buf += "Host: " + server.arg(i) + "<br>";
        }
        else if (server.argName(i) == "port") {
          port = server.arg(i).toInt();
          buf += "Port: " + server.arg(i) + "<br>";
        }
        if (server.argName(i) == "period") {
          period = server.arg(i).toInt();
        }
        else if (server.argName(i) == "unit") {
          String unit = " Milliseconds";
          long per = period;
          if (server.arg(i) == "m") {
            period *= 60000;
            unit = " Minutes";
          }
          else if (server.arg(i) == "s") {
            period *= 1000;
            unit = " Seconds";
          }
          buf += "Period: " + String(per) + unit + "<br><br>";
        }
        else if (server.argName(i) == "power") {
          if (!looking) {
            buf += "Looking for:<br>";
            looking = true;
          }
          powerMonitor = true;
          buf += "- Power Monitor<br>";
        }
        else if (server.argName(i).startsWith("gpioname_")) {
          int gpioNumber = server.argName(i).substring(9).toInt();
          if (server.arg(i).length()) {
            gpioAlias[gpioNumber] = server.arg(i);
          }
        }
        else if (server.argName(i).startsWith("gpio")) {
          if (!looking) {
            buf += "Looking for:<br>";
            looking = true;
          }
          int gpioNumber = server.arg(i).toInt();
          gpioMonitor[gpioNumber] = true;
          pinMode(gpioNumber, INPUT_PULLUP);
          int arg = hasArg(String("gpioname_") + server.arg(i));
          if (server.arg(arg).length()) {
            buf += "- " + server.arg(arg) + " (" + server.argName(i) + ")<br>";
          }
          else {
            buf += "- " + server.argName(i) + "<br>";
          }
        }
        else if (server.argName(i).startsWith("adcname_")) {
          int gpioNumber = server.argName(i).substring(8).toInt();
          if (server.arg(i).length()) {
            gpioAlias[gpioNumber] = server.arg(i);
          }
        }
        else if (server.argName(i).startsWith("adcdivider_")) {
          int gpioNumber = server.argName(i).substring(11).toInt();
          if (server.arg(i).length()) {
            adcDivider[gpioNumber] = server.arg(i).toFloat();
          }
        }
        else if (server.argName(i).startsWith("adc")) {
          if (!looking) {
            buf += "Looking for:<br>";
            looking = true;
          }
          adcMonitor[server.arg(i).toInt()] = true;
          int nameArg = hasArg(String("adcname_") + server.arg(i));
          int divArg = hasArg(String("adcdivider_") + server.arg(i));
          if (server.arg(nameArg).length()) {
            buf += "- " + server.arg(nameArg) + " (" + server.argName(i) + ", divider=" + server.arg(divArg) + ")<br>";
          }
          else {
            buf += "- " + server.argName(i) + " (divider=" + server.arg(divArg) + ")<br>";
          }
        }
      }
      server.send(200, "text/html", buf);
    }
     
    void handleNotFound()
    {
      String message = "File Not Found\n\n";
      message += "URI: ";
      message += server.uri();
      message += "\nMethod: ";
      message += (server.method() == HTTP_GET) ? "GET" : "POST";
      message += "\nArguments: ";
      message += server.args();
      message += "\n";
      for (uint8_t i = 0; i < server.args(); i++) {
        message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
      }
      server.send(404, "text/plain", message);
    }
     
    void setup(void)
    {
      pinMode(led, OUTPUT);
    //  analogSetAttenuation(ADC_6db);
      digitalWrite(led, 0);
      Serial.begin(115200);
      ina226.begin(INA226_I2CADDR);
      ina226.configure(INA226_AVERAGES_16, INA226_BUS_CONV_TIME_8244US, INA226_SHUNT_CONV_TIME_8244US, INA226_MODE_SHUNT_BUS_CONT);
      ina226.calibrate(INA226_OHM, INA226_AMP);
      checkConfig();
      mount();
      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
      Serial.println("");
     
      // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.print("Connected to ");
      Serial.println(ssid);
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      Serial.print("MAC address: ");
      Serial.println(WiFi.macAddress());
      if (MDNS.begin("esp32")) {
        Serial.println("MDNS responder started");
      }
     
      server.on("/index.html", handleRoot);
      server.on("/monitor.html", handleMonitor);
     
      server.on("/inline", []() {
        server.send(200, "text/plain", "this works as well");
      });
     
      server.onNotFound(handleNotFound);
     
      server.begin();
      Serial.println("HTTP server started");
    }
     
    void loop(void)
    {
      String gpio, adc;
      String url = "/log?";
      unsigned long currentMillis = millis();
      static unsigned long previousMillis;
     
      server.handleClient();
      if (started && currentMillis - previousMillis > period) {
        previousMillis = currentMillis;
        if (powerMonitor) {
          float voltage = ina226.readBusVoltage();
          float current = (ina226.readShuntCurrent() + INA226_OFFSET) * 1000;
          Serial.print("INA226: ");
          Serial.print(voltage, 3);
          Serial.print("V, ");
          Serial.print(current, 3);
          Serial.println("mA");
          url += String("VOLTAGE=") + voltage + "&CURRENT=" + current + "&";
        }
        for (int i = 0 ; i < MAX_GPIO ; i++) {
          if (gpioMonitor[i]) {
            gpio = "GPIO" + String(i);
            int state = digitalRead(i);
            if (gpioAlias[i].length()) {
              url += String("GPIO_") + gpioAlias[i] + "=" + state + "&";
            }
            else {
              url += gpio + "=" + state + "&";
            }
          }
          if (adcMonitor[i]) {
            adc = "ADC" + String(i);
            int value = analogRead(i);
            Serial.print("ADC: ");
            Serial.println(value);
            float voltage;
            Serial.print("DIVIDER: ");
            Serial.println(adcDivider[i]);
            if (adcDivider[i]) {
              voltage = VREF * value / 4095 * ATTENUATION * adcDivider[i];
            }
            else {
              voltage = VREF * value / 4095 * ATTENUATION;
            }
            if (gpioAlias[i].length()) {
              url += String("ADC_") + gpioAlias[i] + "=" + voltage + "&";
            }
            else {
              url += adc + "=" + voltage + "&";
            }
          }
        }
        String data = String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + hostName + "\r\n" + "Connection: close\r\n\r\n";
        Serial.println(data);
        Serial.print(hostName);
        Serial.print(":");
        Serial.print(port);
        if (client.connect(hostName, port)) {
          Serial.println(": connected to host");
          Serial.println("Sending data");
          client.println(data);
        }
        else {
          Serial.println(": unable to connect to host");
        }
      }
    }
    Console après Boot
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    13:25:07.547 -> 8.244ms
    13:25:07.547 -> Max possible current:  0.78 A
    13:25:07.547 -> Max current:           0.78 A
    13:25:07.547 -> Max shunt voltage:     0.08 V
    13:25:07.547 -> Max power:             28.09 W
    13:25:07.594 -> 
    13:25:07.594 -> SPIFFS mounted
    13:25:07.594 -> 8283 / 1318001 bytes used
    13:25:07.688 -> index.html: 8011 bytes
    13:25:07.781 -> 
    13:25:08.294 -> .........
    13:25:12.299 -> Connected to Xiaomi_E890
    13:25:12.299 -> IP address: 192.168.1.110
    13:25:12.299 -> MAC address: 0C:B8:15:C4:29:C0
    13:25:12.299 -> MDNS responder started
    13:25:12.299 -> HTTP server started                               <===========================================
    Et lorsque je lance 192.168.1.110/index.html <=====================
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    WEB Power Monitor RUNNING
    Host: 192.168.1.171
    Port: 8080
    Period: 10 Seconds
     
    Looking for:
    - Power Monitor
    - Essai (adc36, divider=)
    resultat sur console toutes les 10 secondes (periode programmée ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    13:29:25.248 -> INA226: -0.001V, -0.100mA
    13:29:25.248 -> ADC: 4095
    13:29:25.248 -> DIVIDER: 0.00
    13:29:25.248 -> GET /log?VOLTAGE=-0.00&CURRENT=-0.10&ADC_Essai=3.51& HTTP/1.1
    13:29:25.248 -> Host: 192.168.1.171
    13:29:25.248 -> Connection: close
    13:29:25.248 -> 
    13:29:25.248 -> 
    13:29:25.248 -> 192.168.1.171:8080: unable to connect to host  <====================================

  6. #26
    Membre Expert
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 595
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 595
    Par défaut
    et tu as lancé cherrypy sur ton serveur ? et tu as lancé ensuite la page du serveur ?
    là dans ton dernier message tout indique que ça marche sauf la connexion au serveur (cherrypy), dont on ne sait pas si tu l'as lancé ou pas

  7. #27
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    et tu as lancé cherrypy sur ton serveur ? et tu as lancé ensuite la page du serveur ?
    là dans ton dernier message tout indique que ça marche sauf la connexion au serveur (cherrypy), dont on ne sait pas si tu l'as lancé ou pas
    j'ai lancé ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Host: 192.168.1.171     <===== PC 
    Port: 8080
    Period: 10 Seconds
     
    Looking for:
    - Power Monitor
    - Essai (adc36, divider=)
    puis l'ESP32 envoi toutes les 10 secondes la valeurs de ADC36 =>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    16:51:05.716 -> INA226: -0.001V, -0.100mA
    16:51:05.716 -> ADC: 4095
    16:51:05.716 -> DIVIDER: 0.00
    16:51:05.716 -> GET /log?VOLTAGE=-0.00&CURRENT=-0.10&ADC_Essai=3.51& HTTP/1.1
    16:51:05.716 -> Host: 192.168.1.171
    16:51:05.716 -> Connection: close
    16:51:05.716 -> 
    16:51:05.716 -> 
    16:51:05.716 -> 192.168.1.171:8080: unable to connect to host

    puis sous shell CherryPy dasn le repertoire Essai que j'ai créé sous Documents
    donc j'ai lancé =>> py index.py et la reponse est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    C:\Users\Utilisateur\Documents\essai>py index.py
    [12/Sep/2025:18:15:14]  SERVER starting at C:\Users\Utilisateur\Documents\essai
    [12/Sep/2025:18:15:14] ENGINE Serving on http://192.168.1.171:8080                <==============
    mais là il bloque et ne rend pas la main , ce qui suppose qu'il n'a pas lancé le serveur , peut-être un problème de version ?

  8. #28
    Membre Expert
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 595
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 595
    Par défaut
    bah c'est normal, cherrypy lance un serveur, et doit tourner pour fonctionner (et là il n'y a plus d'erreur)
    sans fermer la fenêtre, ouvre ton navigateur sur l'ip du serveur/PC et port 8080, tu devrait voir ton résultat


    PS: On peut faire que le serveur se lance en tâche de fond et te rende la main dans l'invite de commande en utilisant la commande start
    (penser à tuer le processus après)

  9. #29
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    (penser à tuer le processus après)
    comment stp ?

    il y a quand même un léger progrès
    sur la console arduino on peut voir ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    20:37:46.314 -> INA226: -0.001V, -0.100mA
    20:37:46.314 -> ADC: 4095
    20:37:46.314 -> DIVIDER: 0.00
    20:37:46.314 -> GET /log?VOLTAGE=-0.00&CURRENT=-0.10&ADC_-------=3.51& HTTP/1.1
    20:37:46.314 -> Host: 192.168.1.171
    20:37:46.314 -> Connection: close
    20:37:46.314 -> 
    20:37:46.314 -> 
    20:37:46.314 -> 192.168.1.171:8080: connected to host
    20:37:46.361 -> Sending data

    mais l'appel en en ligne de commande url => 127.0.0.1:8080 reste malheureusement muet !

  10. #30
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 286
    Billets dans le blog
    48
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    20:37:46.314 -> 192.168.1.171:8080: connected to host
    20:37:46.361 -> Sending data
    Tout va bien donc ? Le serveur CherrryPy démarre, l'esp32 s'y connecte et envoie des données, normal quoi ?

    Je viens seulement de comprendre qu'il y avait aussi un serveur Web sur l'esp32. L'esp32 est donc à la fois un client et un serveur, quel projet !

    Du coup, il se passe quoi dans le navigateur ? Il y a deux pages à consulter :
    - celle du serveur CherryPy sur le PC à l'url http://localhost:8080 ou http://192.168.1.171:8080
    - celle du serveur de l'esp32 à l'url http://192.168.1.110

    Les pages s'affichent-elles bien ? La page du PC CherryPy trace des courbes si j'ai bien compris, qu'en est-il ? Le PC fait aussi des sauvegardes sur fichier csv, le fichier est-il créé ?

  11. #31
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    Du coup, il se passe quoi dans le navigateur ? Il y a deux pages à consulter :
    - celle du serveur CherryPy sur le PC à l'url http://localhost:8080 ou http://192.168.1.171:8080
    - celle du serveur de l'esp32 à l'url http://192.168.1.110
    Oui exact 2 pages :
    - l'une permet de configurer l'entrée à surveiller , ici j'ai choisi ADC36 où j'ai mis à VCC
    on l'active à partir de 192.168.1.110/index.html et çà fonctionne très bien sans problème d'où l'usage de l'IP de l'ESP32

    - l'autre devrait être déclenchée pour visualiser les courbes à l'aide du localhost:8080 ou 192.168.1.171:8080
    et c'est là que le problème intervient , je n'arrive pas à lancer cette page

    http://192.168.1.171:8080/ a renvoyé une erreur.
    Code d’erreur : 404 Not Found


    Les pages s'affichent-elles bien ?
    non donc pour la seconde

    La page du PC CherryPy trace des courbes si j'ai bien compris
    Oui c'est cela , les données sont celles définies périodiquement par l'ESP32 ( voir 1ere page)


    Je viens seulement de comprendre qu'il y avait aussi un serveur Web sur l'esp32. L'esp32 est donc à la fois un client et un serveur, quel projet !
    Oui c'est un projet complexe , trop peut-être pour moi j'essaie de comprendre, tu as du t'en apercevoir
    je rends hommage au créateur du projet


    Le PC fait aussi des sauvegardes sur fichier csv, le fichier est-il créé ?
    Oui c'est exact, mais comme je n'ai pas affiché la page , je ne sais pas si le fichier est créé ( par défaut il s'appelle je crois log.csv )

  12. #32
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 286
    Billets dans le blog
    48
    Par défaut
    Ok, le serveur cherrypy est démarré, mais il ne sert pas la page index.html qui est pourtant bien exposée (méthode index dans le code).

    Mais je vois que le code est ancien, en Python 2.7, il y a sûrement des adaptations à faire avec une version récente cherrypy...

    Par exemple le lancement du serveur :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    cherrypy.root = HomePage()
    if __name__ == '__main__': 
        cherrypy.config.update('web-power-monitor.conf')
        cherrypy.log('SERVER starting at %s' % os.getcwd())
        cherrypy.server.start()

    J'ai l'impression que le lancement est plus simple maintenant :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if __name__ == '__main__':
        cherrypy.config.update('web-power-monitor.conf')
        cherrypy.quickstart(HomePage())

    À voir avec cette nouvelle méthode quickstart...

  13. #33
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    Bonjour f-leb

    Cool ,
    çà progresse un peu voici la réponse à 192.168.1.171:8080

    il y a effectivement un problème de version, l'idée serait peut-être de mettre une ancienne version de CherryPy ( par ex : 18.6 ) en lieu et place de celle-ci
    mais comment faire pour désinstaller proprement celle existante actuellement ?
    Images attachées Images attachées  

  14. #34
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 286
    Billets dans le blog
    48
    Par défaut
    Je pense que tu n'es pas loin du but, ici ce n'est pas CherryPy qui est en cause mais la version de Python (Python 2.x <--> Python 3.x).

    Il suffit de remplacer :
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    k = self.data.keys()

    par

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    k = list(self.data.keys()) # conversion des clés en liste avant de trier

    Tu as d'autres endroits dans le code avec le même genre de conversion en liste à faire avant le tri.

    Et tu auras peut-être encore d'autres soucis de ce genre à cause de la version de Python, mais assez simples à corriger.

  15. #35
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    Salut f-leb

    merci encore .....

    J'ai eu la mauvaise idée ce matin de désinstaller la version Python3.13 pour Python2.7 (celle utilisée par l'auteur )
    mal m'en a pris car la version 2.7 ne comporte pas PIP et tout le reste et je suis perdu
    bref maintenant je suis dans le noir

    mais je continue ....je vais reinstaller python3.13 et cherrypy18.10 donc

  16. #36
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 286
    Billets dans le blog
    48
    Par défaut
    Python 2.x est officiellement mort depuis 2020, always forward, never back

  17. #37
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    Citation Envoyé par f-leb Voir le message
    Je pense que tu n'es pas loin du but, ici ce n'est pas CherryPy qui est en cause mais la version de Python (Python 2.x <--> Python 3.x).

    Il suffit de remplacer :
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    k = self.data.keys()

    par

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    k = list(self.data.keys()) # conversion des clés en liste avant de trier

    Tu as d'autres endroits dans le code avec le même genre de conversion en liste à faire avant le tri.

    Et tu auras peut-être encore d'autres soucis de ce genre à cause de la version de Python, mais assez simples à corriger.
    Désolé f-leb mais çà n'a pas l'air de fonctionner , j'ai changé qu'1 seule ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    C:\Users\Utilisateur\Documents\essai>py index.py
      File "C:\Users\Utilisateur\Documents\essai\index.py", line 53
        k = list(self.data.keys()) # conversion des clés en liste avant de trier
    TabError: inconsistent use of tabs and spaces in indentation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import sys, os, locale, logging
    from datetime import datetime
    from dateutil import parser
    import cherrypy
    from cherrypy.lib.static import serve_file 
    from template import Template
     
    logger = logging.getLogger('index')
     
    current_dir = os.path.realpath(os.path.curdir)
     
    gpioSerie = """
            {
              name: '%s',
              type: 'spline',
              data: [%s],
            },
    		"""
     
    adcSerie = """
            {
              name: '%s',
              type: 'spline',
              data: [%s],
              tooltip: {
                  valueSuffix: 'V'
              },
            },
    		"""
     
    class HomePage(object):
     
    	def __init__(self):
    		logger.setLevel(logging.DEBUG)
    		ch = logging.StreamHandler()
    		ch.setLevel(logging.DEBUG)
    		formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    		ch.setFormatter(formatter)
    		logger.addHandler(ch)
    		self.data = {}
    		self.xLabel = 's'
     
    	def load(self, fileName):
    		f = open(fileName, 'r')
    		return f.read()
     
    	def getXData(self):
    		data = ''
    		#k = self.data.keys()
            k = list(self.data.keys()) # conversion des clés en liste avant de trier
    		k.sort()
    		for dt in k:
    			if len(data) > 0:
    				data += ', '
    			data += "Date.UTC(%s, %s, %s, %s, %s, %s, %s)" % (dt.year, dt.month-1, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond/1000)
     
    		return data
     
    	def hasPowerData(self):
    		k = self.data.keys()
    		k.sort()
    		if len(k) and 'CURRENT' in self.data[k[0]]:
    			return True
    		return False
     
    	def hasGpioData(self):
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			gpioList = self.data[k[0]]
    			for gpio in gpioList:
    				serie = ''
    				if gpio.startswith('GPIO'):
    					return True
    		return False
     
    	def hasAdcData(self):
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			adcList = self.data[k[0]]
    			for adc in adcList:
    				serie = ''
    				if adc.startswith('ADC'):
    					return True
    		return False
     
    	def getCurrentData(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k) and 'CURRENT' in self.data[k[0]]:
    			for entry in k:
    				if len(data) > 0:
    					data += ', '
    				data += self.data[entry]['CURRENT']
    		return data
     
    	def getVoltageData(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k) and 'VOLTAGE' in self.data[k[0]]:
    			for entry in k:
    				if len(data) > 0:
    					data += ', '
    				data += self.data[entry]['VOLTAGE']
    		return data
     
    	def getGpioSeries(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			gpioList = self.data[k[0]]
    			for gpio in gpioList:
    				serie = ''
    				if gpio.startswith('GPIO'):
    					id = gpio
    					if not gpio[4:].isdigit():
    						id = gpio[5:]
    					for entry in k:
    						if len(serie) > 0:
    							serie += ', '
    						serie += self.data[entry][gpio]
    					data += gpioSerie % (id, serie)
    		return data
     
    	def getAdcSeries(self):
    		data = ''
    		k = self.data.keys()
    		k.sort()
    		if len(k):
    			adcList = self.data[k[0]]
    			for adc in adcList:
    				serie = ''
    				if adc.startswith('ADC'):
    					id = adc
    					if not adc[3:].isdigit():
    						id = adc[4:]
    					for entry in k:
    						if len(serie) > 0:
    							serie += ', '
    						serie += self.data[entry][adc]
    					data += adcSerie % (id, serie)
    		return data
     
    	@cherrypy.expose
    	def favicon_ico(self):
    		current_dir = os.path.realpath(os.path.curdir)
    		return serve_file(current_dir + '/favicon.ico')
     
    	@cherrypy.expose
    	def index(self):
    		tmpl = self.load('index.html')
    		nameSpace = {'XDATA': self.getXData(),
    					   	'XLABEL': self.xLabel,
    					   	'CURRENT_DATA': self.getCurrentData(),
    						'VOLTAGE_DATA': self.getVoltageData(),
    						'GPIO_SERIES': self.getGpioSeries(),
    						'ADC_SERIES': self.getAdcSeries(),
    						'DISPLAY_POWER': "block" if self.hasPowerData() else "none",
    						'DISPLAY_GPIO': "block" if self.hasGpioData() else "none",
    						'DISPLAY_ADC': "block" if self.hasAdcData() else "none"
    					}
    		return Template(tmpl, searchList=[nameSpace]).respond()
     
    	@cherrypy.expose
    	def clear(self):
    		self.data = {}
    		raise cherrypy.HTTPRedirect("/") 
     
    	@cherrypy.expose
    	def export(self, filename='log.csv'):
    		k = self.data.keys()
    		k.sort()
    		data = 'TIME'
    		if len(k):
    			f = open(filename, 'w')
    			columns = self.data[k[0]].keys()
    			columns.sort()
    			for col in columns:
    				data += ';'
    				data += col
    			data += '\n'
    			f.write(data)
    			data = ''
    			for entry in k:
    				data += str(entry)
    				for col in columns:
    					data += ';'
    					data += self.data[entry][col]
    				data += '\n'
    				f.write(data)
    				data = ''
    			f.close()
    			path = os.path.join(os.getcwd(), filename)
    			return serve_file(path, 'application/x-download', 'attachment', os.path.basename(path))
     
    	@cherrypy.expose
    	def log(self, **kwargs):
    		logger.debug('log %s' % kwargs)
    		if "dt" in kwargs:
    			dt = parser.parse(kwargs["dt"])
    		else:
    			dt = datetime.now()
    		self.data[dt] = {}
    		for arg in kwargs.keys():
    			self.data[dt][arg] = kwargs[arg]
    		tmpl = self.load('index.html')
    		return "OK"
     
    cherrypy.root = HomePage()
    if __name__ == '__main__':
        cherrypy.config.update('web-power-monitor.conf')
        cherrypy.quickstart(HomePage())

  18. #38
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 286
    Billets dans le blog
    48
    Par défaut
    L'indentation du code fait partie de la syntaxe en Python.


    Ici, il manque une indentation à la ligne 4:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	def getXData(self):
    		data = ''
    		#k = self.data.keys()
            k = list(self.data.keys()) # conversion des clés en liste avant de trier
    		k.sort()

    Il faut avoir:
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	def getXData(self):
    		data = ''
    		#k = self.data.keys()
            	k = list(self.data.keys()) # conversion des clés en liste avant de trier
    		k.sort()

    et puis le message TabError: inconsistent use of tabs and spaces in indentation indique qu'un fichier Python ne doit pas mélanger des tabulations [tab] et des espaces [space] dans les indentations, même si visuellement le résultat est identique.
    Tu fais toutes tes indentations soit avec [tab], soit avec [space] mais pas en mélangeant les deux. Les éditeurs Python modernes savant gérer l'indentation et proposent de remplacer les tabulations par des espaces ou l'inverse.

    Tu aurais quand même dû te familiariser avec Python en consultant quelques tutoriels avant de te lancer dans un tel projet. Python, esp32, réseaux et framework web, c'est quand même assez complexe dans les interactions en plus des langages Python et Arduino

    Mais courage, tu n'es pas si loin du but

  19. #39
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    Je ne le savais pas et je viens juste de corriger maintenant çà va mieux

    j'ai encore un petit souci pour le fichier export et après çà sera bon je crois !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    	@cherrypy.expose
    	def export(self, filename='log.csv'):
    		k = list(self.data.keys()) # conversion des clés en liste avant de trier
    		k.sort()
    		data = 'TIME'
    		if len(k):
    			f = open(filename, 'w')
    			columns = self.data[k[0]].keys()     <===============================
    			columns.sort()
    			for col in columns:
    				data += ';'
    				data += col
    			data += '\n'
    			f.write(data)
    			data = ''
    			for entry in k:
    				data += str(entry)
    				for col in columns:
    					data += ';'
    					data += self.data[entry][col]
    				data += '\n'
    				f.write(data)
    				data = ''
    			f.close()
    			path = os.path.join(os.getcwd(), filename)
    			return serve_file(path, 'application/x-download', 'attachment', os.path.basename(path))
    Images attachées Images attachées  

  20. #40
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 070
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 070
    Par défaut
    J'ai remplacé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    columns = self.data[k[0]].keys()     <===============================
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    columns = list(self.data[k[0]].keys())     <===============================
    et çà fonctionne !!!!

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. [python] en remplacement de [php] [cherrypy]
    Par pfeuh dans le forum Général Python
    Réponses: 5
    Dernier message: 22/09/2011, 17h01
  2. cherrypy ou module CGI ?
    Par Luke spywoker dans le forum Réseau/Web
    Réponses: 3
    Dernier message: 11/07/2011, 21h47
  3. erreur cherrypy creation session
    Par menthol34 dans le forum Réseau/Web
    Réponses: 2
    Dernier message: 17/02/2011, 15h40
  4. Cherrypy Daemonizer et abspath
    Par suckthewindow dans le forum Réseau/Web
    Réponses: 1
    Dernier message: 17/02/2011, 12h58
  5. Cheetah et Cherrypy
    Par suckthewindow dans le forum Réseau/Web
    Réponses: 2
    Dernier message: 07/04/2008, 10h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo