Jump to content

Arduino Hostname Generator

Aelita Sophie
Go to solution Solved by Unimportant,
14 hours ago, Aelita Sophie said:

<snip>

char* hostName = "P1Meter";

"P1Meter" is a string literal, stored in read only memory (Or memory ear-marked as read only at least). You should not try and modify it, as that causes undefined behavior, yet you do:

char* newname = strcat(hostName, deblank(MAC_Adress));

"strcat" will try to append a copy of whatever string "deblank(MAC_Adress)" returns to the string pointed to by "hostName", thus trying to modify the read only literal. For that reason one should always make such string literals, that you do not intend to modify, const:

const char* example = "The quick brown fox, whatever...";

That would've caught the error at compile time.

 

Secondly, you should make sure the destination string has enough room to hold the complete string, which is also not the case.

To fix it,make "hostName" a array, with enough spare room to hold the entire resulting string:

char hostName[25] = "P1Meter";  //25 is just a example here, change this to your needs.
				//Do not forget to allow one extra space for the terminating 0.

 

So for my DIY IoT setup, I'll be using loads of ESP8266 (or alike) chips to connect everything together to 1 main server by WiFi.

Right now I'm working on a Serial P1 Smart Meter reader, so it can post my energy and gas usage to my server. This function completely works. The telegram gets decoded nicely and send to the server. Thinking further, I want to make the chips recognizeable by hostname. Hostname will be <functionchip>[1234], for example P1Meter6001. Where 6001 is actually the 60:01 which comes from its mac adres.

 

Now obviously, I'll only have 1 P1Meter, but light switches and such will be around a lot more.

I've got everything about it sorted out, but somehow, when I "dynamically" generate its hostname, it just fails to connect to the WiFi SSID. When I disable that 1 line of code that calls upon the function to generate it. (Which will make the hostname just P1Meter) it works fine. What am I doing wrong here?

 

#include <TimeLib.h>
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPClient.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include "CRC16.h"

//===Change values from here===

//===WiFi setup================
const char* ssid = "--deleted-";
const char* password = "--deleted-";


char* hostName = "P1Meter";
const bool outputOnSerial = true;
//===Change values to here===

uint8_t MAC_array[6];
char MAC_char[18];

// Vars to store meter readings
long mEVLT = 0; //Meter reading Electrics - consumption low tariff
long mEVHT = 0; //Meter reading Electrics - consumption high tariff
long mEOLT = 0; //Meter reading Electrics - return low tariff
long mEOHT = 0; //Meter reading Electrics - return high tariff
long mEAV = 0;  //Meter reading Electrics - Actual consumption
long mEAT = 0;  //Meter reading Electrics - Actual return
long mGAS = 0;    //Meter reading Gas
long prevGAS = 0;


#define MAXLINELENGTH 64 // longest normal line is 47 char (+3 for \r\n\0)
char telegram[MAXLINELENGTH];

#define SERIAL_RX     D5  // pin for SoftwareSerial RX
SoftwareSerial mySerial(SERIAL_RX, -1, true, MAXLINELENGTH); // (RX, TX. inverted, buffer)

unsigned int currentCRC = 0;

char * deblank(char *str)
{
  char *out = str, *put = str;

  for(; *str != '\0'; ++str)
  {
    if(*str != ':'){
      *put++ = *str;
    }
  }
  *put = '\0';

  return out;
}

char* CreateHostname(char MAC_Adress[]){
 MAC_Adress[6] = '\0';
 char* newname = strcat(hostName, deblank(MAC_Adress));
  return newname;
}

void SendToDomoLog(char* message)
{
  char url[512];
  sprintf(url, "http://%s:%d/json.htm?type=command&param=addlogmessage&message=%s", domoticzIP, domoticzPort, message);
}

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);

  WiFi.macAddress(MAC_array);
    for (int i = 0; i < sizeof(MAC_array); ++i){
      sprintf(MAC_char,"%s%02x:",MAC_char,MAC_array[i]);
    }
  
  hostName = CreateHostname(MAC_char);
  Serial.println(hostName);
  WiFi.hostname(hostName);
  WiFi.begin(ssid, password);
  
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }
  if(WiFi.status() == WL_CONNECTED){
   // WiFi.hostname
  }
  mySerial.begin(115200);

  // Port defaults to 8266
  ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname(hostName);

  // No authentication by default
  //ArduinoOTA.setPassword((const char *)"123");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

Monitor output:

 ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v3de0c112
~ld
üBooting
60:01:94:2b:c2:3d:
P1Meter6001
Connection Failed! Rebooting...

 

Main RIG: i7 4770k ~ 4.8Ghz | Intel HD Onboard (enough for my LoL gaming) | Samsung 960 Pro 256GB NVMe | 32GB (4x 8GB) Kingston Savage 2133Mhz DDR3 | MSI Z97 Gaming 7 | ThermalTake FrioOCK | MS-Tech (puke) 700W | Windows 10 64Bit

Mining RIG: AMD A6-9500 | ASRock AB350 Pro | 4GB DDR4 | 500GB 2.5 Inch HDD | 2x MSI AERO GTX 1060 6GB (Core/Memory/TDP/Avg Temp +160/+800/120%/45c) | 1x Asus Strix GTX 970 (+195/+400/125%/55c) | 1x KFA2 GTX 960 (+220/+500/120%/70c) | Corsair GS800 800W | HP HSTNS-PD05 1000W | (Modded) Inter-Tech IPC 4U-4129-N Rackmount Case

Guest RIG: FX6300 | AMD HD7870 | Kingston HyperX 128GB SSD | 16GB (2x 8GB) G.Skill Ripjaws 1600Mhz DDR3 | Some ASRock 970 Mobo | Stock Heatsink | some left over PSU  | Windows 10 64Bit

VM Server: HP Proliant DL160 G6 | 2x Intel Xeon E5620 @ 2.4Ghz 4c/8t (8c/16t total) | 16GB (8x 2GB) HP 1066Mhz ECC DDR3 | 2x Western Digital Black 250GB HDD | VMWare ESXI

Storage Node: 2x Intel Xeon E5520 @ 2.27Ghz 4c/8t (8c/16t total) | Intel ServerBoard S5500HCV | 36GB (9x 4GB) 1333Mhz ECC DDR3 | 3x Seagate 2TB 7200RPM | 4x Western Digital Caviar Green 2TB

Link to comment
Share on other sites

Link to post
Share on other sites

14 hours ago, Aelita Sophie said:

<snip>

char* hostName = "P1Meter";

"P1Meter" is a string literal, stored in read only memory (Or memory ear-marked as read only at least). You should not try and modify it, as that causes undefined behavior, yet you do:

char* newname = strcat(hostName, deblank(MAC_Adress));

"strcat" will try to append a copy of whatever string "deblank(MAC_Adress)" returns to the string pointed to by "hostName", thus trying to modify the read only literal. For that reason one should always make such string literals, that you do not intend to modify, const:

const char* example = "The quick brown fox, whatever...";

That would've caught the error at compile time.

 

Secondly, you should make sure the destination string has enough room to hold the complete string, which is also not the case.

To fix it,make "hostName" a array, with enough spare room to hold the entire resulting string:

char hostName[25] = "P1Meter";  //25 is just a example here, change this to your needs.
				//Do not forget to allow one extra space for the terminating 0.

 

Link to comment
Share on other sites

Link to post
Share on other sites

12 hours ago, Unimportant said:

char* hostName = "P1Meter";

"P1Meter" is a string literal, stored in read only memory (Or memory ear-marked as read only at least). You should not try and modify it, as that causes undefined behavior, yet you do:


char* newname = strcat(hostName, deblank(MAC_Adress));

"strcat" will try to append a copy of whatever string "deblank(MAC_Adress)" returns to the string pointed to by "hostName", thus trying to modify the read only literal. For that reason one should always make such string literals, that you do not intend to modify, const:


const char* example = "The quick brown fox, whatever...";

That would've caught the error at compile time.

 

Secondly, you should make sure the destination string has enough room to hold the complete string, which is also not the case.

To fix it,make "hostName" a array, with enough spare room to hold the entire resulting string:


char hostName[25] = "P1Meter";  //25 is just a example here, change this to your needs.
				//Do not forget to allow one extra space for the terminating 0.

 

Thank you, assigning enough room was probably the issue. Seems to be working fine now. Thanks a bunch!

Main RIG: i7 4770k ~ 4.8Ghz | Intel HD Onboard (enough for my LoL gaming) | Samsung 960 Pro 256GB NVMe | 32GB (4x 8GB) Kingston Savage 2133Mhz DDR3 | MSI Z97 Gaming 7 | ThermalTake FrioOCK | MS-Tech (puke) 700W | Windows 10 64Bit

Mining RIG: AMD A6-9500 | ASRock AB350 Pro | 4GB DDR4 | 500GB 2.5 Inch HDD | 2x MSI AERO GTX 1060 6GB (Core/Memory/TDP/Avg Temp +160/+800/120%/45c) | 1x Asus Strix GTX 970 (+195/+400/125%/55c) | 1x KFA2 GTX 960 (+220/+500/120%/70c) | Corsair GS800 800W | HP HSTNS-PD05 1000W | (Modded) Inter-Tech IPC 4U-4129-N Rackmount Case

Guest RIG: FX6300 | AMD HD7870 | Kingston HyperX 128GB SSD | 16GB (2x 8GB) G.Skill Ripjaws 1600Mhz DDR3 | Some ASRock 970 Mobo | Stock Heatsink | some left over PSU  | Windows 10 64Bit

VM Server: HP Proliant DL160 G6 | 2x Intel Xeon E5620 @ 2.4Ghz 4c/8t (8c/16t total) | 16GB (8x 2GB) HP 1066Mhz ECC DDR3 | 2x Western Digital Black 250GB HDD | VMWare ESXI

Storage Node: 2x Intel Xeon E5520 @ 2.27Ghz 4c/8t (8c/16t total) | Intel ServerBoard S5500HCV | 36GB (9x 4GB) 1333Mhz ECC DDR3 | 3x Seagate 2TB 7200RPM | 4x Western Digital Caviar Green 2TB

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×