Skip to content

Commit

Permalink
Add a 64bit version of the millis() function
Browse files Browse the repository at this point in the history
millis() will rollover after 50 days leading to some interesting bugs.
Create a 64bit version.

Signed-off-by: jgstroud <[email protected]>
  • Loading branch information
jgstroud committed Dec 23, 2024
1 parent 216fa13 commit 638ebe3
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 48 deletions.
48 changes: 24 additions & 24 deletions src/comms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ uint32_t last_saved_code = 0;

static const uint8_t RX_LENGTH = 2;
typedef uint8_t RxPacket[RX_LENGTH * 4];
unsigned long last_rx;
unsigned long last_tx;
uint64_t last_rx;
uint64_t last_tx;

bool wallplateBooting = false;
bool wallPanelDetected = false;
Expand Down Expand Up @@ -190,7 +190,7 @@ void wallPlate_Emulation()
if (wallPanelDetected)
return;

unsigned long currentMillis = millis();
uint64_t currentMillis = millis64();
static unsigned long lastRequestMillis = 0;
static bool emulateWallPanel = false;
static unsigned long serialDetected = 0;
Expand Down Expand Up @@ -268,7 +268,7 @@ void comms_loop_sec1()
if (sw_serial.available())
{
uint8_t ser_byte = sw_serial.read();
last_rx = millis();
last_rx = millis64();

if (!reading_msg)
{
Expand Down Expand Up @@ -304,7 +304,7 @@ void comms_loop_sec1()
gotMessage = true;
}

if (gotMessage == false && (millis() - last_rx) > 100)
if (gotMessage == false && (millis64() - last_rx) > 100)
{
RINFO("RX message timeout");
// if we have a partial packet and it's been over 100ms since last byte was read,
Expand Down Expand Up @@ -332,7 +332,7 @@ void comms_loop_sec1()
manual_recovery();
if (motionTriggers.bit.doorKey)
{
garage_door.motion_timer = millis() + 5000;
garage_door.motion_timer = millis64() + 5000;
garage_door.motion = true;
notify_homekit_motion();
}
Expand Down Expand Up @@ -548,7 +548,7 @@ void comms_loop_sec1()
notify_homekit_light();
if (motionTriggers.bit.lightKey)
{
garage_door.motion_timer = millis() + 5000;
garage_door.motion_timer = millis64() + 5000;
garage_door.motion = true;
notify_homekit_motion();
}
Expand Down Expand Up @@ -576,7 +576,7 @@ void comms_loop_sec1()
notify_homekit_current_lock();
if (motionTriggers.bit.lockKey)
{
garage_door.motion_timer = millis() + 5000;
garage_door.motion_timer = millis64() + 5000;
garage_door.motion = true;
notify_homekit_motion();
}
Expand All @@ -592,13 +592,13 @@ void comms_loop_sec1()
//
PacketAction pkt_ac;
static unsigned long cmdDelay = 0;
unsigned long now;
uint64_t now;
bool okToSend = false;

if (!q_isEmpty(&pkt_q))
{

now = millis();
now = millis64();

// if there is no wall panel, no need to check 200ms since last rx
// (yes some duped code here, but its clearer)
Expand Down Expand Up @@ -798,7 +798,7 @@ void comms_loop_sec2()
notify_homekit_target_lock();
if (motionTriggers.bit.lockKey)
{
garage_door.motion_timer = millis() + 5000;
garage_door.motion_timer = millis64() + 5000;
garage_door.motion = true;
notify_homekit_motion();
}
Expand Down Expand Up @@ -832,7 +832,7 @@ void comms_loop_sec2()
notify_homekit_light();
if (motionTriggers.bit.lightKey)
{
garage_door.motion_timer = millis() + 5000;
garage_door.motion_timer = millis64() + 5000;
garage_door.motion = true;
notify_homekit_motion();
}
Expand Down Expand Up @@ -863,7 +863,7 @@ void comms_loop_sec2()
/* When we get the motion detect message, notify HomeKit. Motion sensor
will continue to send motion messages every 5s until motion stops.
set a timer for 5 seconds to disable motion after the last message */
garage_door.motion_timer = millis() + 5000;
garage_door.motion_timer = millis64() + 5000;
if (!garage_door.motion)
{
garage_door.motion = true;
Expand All @@ -883,7 +883,7 @@ void comms_loop_sec2()
}
if (pkt.m_data.value.door_action.pressed && motionTriggers.bit.doorKey)
{
garage_door.motion_timer = millis() + 5000;
garage_door.motion_timer = millis64() + 5000;
garage_door.motion = true;
notify_homekit_motion();
}
Expand Down Expand Up @@ -980,7 +980,7 @@ bool transmitSec1(byte toSend)
}

sw_serial.write(toSend);
last_tx = millis();
last_tx = millis64();

// RINFO("SEC1 SEND BYTE: %02X",toSend);

Expand Down Expand Up @@ -1054,7 +1054,7 @@ bool process_PacketAction(PacketAction &pkt_ac)
success = transmitSec1(pkt_ac.pkt.m_data.value.cmd);
if (success)
{
last_tx = millis();
last_tx = millis64();
// RINFO("sending 0x%02X query", pkt_ac.pkt.m_data.value.cmd);
}
}
Expand All @@ -1067,7 +1067,7 @@ bool process_PacketAction(PacketAction &pkt_ac)
success = transmitSec1(secplus1Codes::DoorButtonPress);
if (success)
{
last_tx = millis();
last_tx = millis64();
RINFO("sending DOOR button press");
}
}
Expand All @@ -1076,7 +1076,7 @@ bool process_PacketAction(PacketAction &pkt_ac)
success = transmitSec1(secplus1Codes::DoorButtonRelease);
if (success)
{
last_tx = millis();
last_tx = millis64();
RINFO("sending DOOR button release");
}
}
Expand All @@ -1091,7 +1091,7 @@ bool process_PacketAction(PacketAction &pkt_ac)
success = transmitSec1(secplus1Codes::LightButtonPress);
if (success)
{
last_tx = millis();
last_tx = millis64();
RINFO("sending LIGHT button press");
}
}
Expand All @@ -1100,7 +1100,7 @@ bool process_PacketAction(PacketAction &pkt_ac)
success = transmitSec1(secplus1Codes::LightButtonRelease);
if (success)
{
last_tx = millis();
last_tx = millis64();
RINFO("Sending LIGHT button release");
}
}
Expand All @@ -1115,7 +1115,7 @@ bool process_PacketAction(PacketAction &pkt_ac)
success = transmitSec1(secplus1Codes::LockButtonPress);
if (success)
{
last_tx = millis();
last_tx = millis64();
RINFO("sending LOCK button press");
}
}
Expand All @@ -1124,7 +1124,7 @@ bool process_PacketAction(PacketAction &pkt_ac)
success = transmitSec1(secplus1Codes::LockButtonRelease);
if (success)
{
last_tx = millis();
last_tx = millis64();
RINFO("sending LOCK button release");
}
}
Expand Down Expand Up @@ -1452,9 +1452,9 @@ void manual_recovery()
if (force_recover.push_count++ == 0)
{
RINFO("Push count start");
force_recover.timeout = millis() + 3000;
force_recover.timeout = millis64() + 3000;
}
else if (millis() > force_recover.timeout)
else if (millis64() > force_recover.timeout)
{
RINFO("Push count reset");
force_recover.push_count = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ void printMessageLog(Print &outputDev)
}
#endif
outputDev.write("Server uptime (ms): ");
outputDev.println(millis());
outputDev.println(millis64());
outputDev.write("Firmware version: ");
outputDev.write(AUTO_VERSION);
outputDev.println();
Expand Down
10 changes: 5 additions & 5 deletions src/ratgdo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ void IRAM_ATTR isr_obstruction()

void obstruction_timer()
{
unsigned long current_millis = millis();
static unsigned long last_millis = 0;
uint64_t current_millis = millis64();
static uint64_t last_millis = 0;

// the obstruction sensor has 3 states: clear (HIGH with LOW pulse every 7ms), obstructed (HIGH), asleep (LOW)
// the transitions between awake and asleep are tricky because the voltage drops slowly when falling asleep
Expand Down Expand Up @@ -338,7 +338,7 @@ void service_timer_loop()
// Service the Obstruction Timer
obstruction_timer();

unsigned long current_millis = millis();
uint64_t current_millis = millis64();

#ifdef NTP_CLIENT
if (enableNTP && clockSet && lastRebootAt == 0)
Expand Down Expand Up @@ -419,9 +419,9 @@ void LED::flash(unsigned long ms)
if (ms)
{
digitalWrite(LED_BUILTIN, activeState);
resetTime = millis() + ms;
resetTime = millis64() + ms;
}
else if ((digitalRead(LED_BUILTIN) == activeState) && (millis() > resetTime))
else if ((digitalRead(LED_BUILTIN) == activeState) && (millis64() > resetTime))
{
digitalWrite(LED_BUILTIN, idleState);
}
Expand Down
4 changes: 2 additions & 2 deletions src/ratgdo.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct GarageDoor
GarageDoorTargetState target_state;
bool obstructed;
bool has_motion_sensor;
unsigned long motion_timer;
uint64_t motion_timer;
bool motion;
bool light;
LockCurrentState current_lock;
Expand All @@ -78,7 +78,7 @@ class LED
private:
uint8_t activeState = 0;
uint8_t idleState = 1; // opposite of active
unsigned long resetTime = 0; // Stores time when LED should return to idle state
uint64_t resetTime = 0; // Stores time when LED should return to idle state
bool initialized = false;
bool enabled = true;

Expand Down
10 changes: 4 additions & 6 deletions src/utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ bool enableNTP = false;
unsigned long lastRebootAt = 0;
int32_t savedDoorUpdateAt = 0;

uint64_t IRAM_ATTR millis64() {
return micros64() / 1000;
}

bool get_tz()
{
WiFiClient client;
Expand Down Expand Up @@ -306,7 +310,6 @@ void load_all_config_settings()
RINFO(" softAPmode: %s", userConfig->softAPmode ? "true" : "false");
RINFO(" syslogEn: %s", userConfig->syslogEn ? "true" : "false");
RINFO(" syslogIP: %s", userConfig->syslogIP);
RINFO(" syslogPort: %d", userConfig->syslogPort);
}

void sync_and_restart()
Expand Down Expand Up @@ -406,7 +409,6 @@ void write_config_to_file()
file.printf_P(PSTR("softAPmode,,%s\n"), userConfig->softAPmode ? "true" : "false");
file.printf_P(PSTR("syslogEn,,%s\n"), userConfig->syslogEn ? "true" : "false");
file.printf_P(PSTR("syslogIP,,%s\n"), userConfig->syslogIP);
file.printf_P(PSTR("syslogPort,,%d\n"), userConfig->syslogPort);
file.close();
}

Expand Down Expand Up @@ -522,10 +524,6 @@ bool read_config_from_file()
{
strlcpy(userConfig->syslogIP, value, sizeof(userConfig->syslogIP));
}
else if (!strcmp(key, "syslogPort"))
{
userConfig->syslogPort = atoi(value);
}
}
file.close();
return true;
Expand Down
1 change: 1 addition & 0 deletions src/utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ typedef union
extern motionTriggersUnion motionTriggers;

// Function declarations
uint64_t millis64();
void load_all_config_settings();
void sync_and_restart();

Expand Down
6 changes: 3 additions & 3 deletions src/web.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ char *json = NULL;
void web_loop()
{
loop_id = LOOP_WEB;
unsigned long upTime = millis();
uint64_t upTime = millis64();
START_JSON(json);
if (garage_door.active && garage_door.current_state != lastDoorState)
{
Expand Down Expand Up @@ -590,7 +590,7 @@ void handle_everything()

void handle_status()
{
unsigned long upTime = millis();
uint64_t upTime = millis64();
#define paired homekit_is_paired()
#define accessoryID arduino_homekit_get_running_server() ? arduino_homekit_get_running_server()->accessory_id : "Inactive"
#define clientCount arduino_homekit_get_running_server() ? arduino_homekit_get_running_server()->nfds : 0
Expand Down Expand Up @@ -1016,7 +1016,7 @@ void SSEheartbeat(SSESubscription *s)
static int lastClientCount = 0;

START_JSON(json);
ADD_INT(json, "upTime", millis());
ADD_INT(json, "upTime", millis64());
ADD_INT(json, "freeHeap", free_heap);
ADD_INT(json, "minHeap", min_heap);
ADD_INT(json, "minStack", ESP.getFreeContStack());
Expand Down
14 changes: 7 additions & 7 deletions src/wifi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "wifi.h"

// support for changeing WiFi settings
unsigned long wifiConnectTimeout = 0;
uint64_t wifiConnectTimeout = 0;
// support for scaning WiFi networks
bool wifiNetsCmp(wifiNet_t a, wifiNet_t b)
{
Expand Down Expand Up @@ -195,7 +195,7 @@ void wifi_connect()
RINFO("Connecting to SSID: %s", wifiConf.ssid);
}
RINFO("Starting WiFi connecting in background");
wifiConnectTimeout = millis() + 30000;
wifiConnectTimeout = millis64() + 30000;
WiFi.begin(); // use credentials stored in flash
IRAM_END("Wifi initialized");
}
Expand All @@ -207,7 +207,7 @@ void improv_loop()
static unsigned long gw_ping_timeout = 10000;
static unsigned long gw_report_interval = 0;
// Once a minute ping the Gateway and log
unsigned long now = millis();
uint64_t now = millis64();
if (now > gw_ping_timeout) {
gw_ping_timeout = now + 60000;
if (Ping.ping(WiFi.gatewayIP(), 1)) {
Expand Down Expand Up @@ -237,14 +237,14 @@ void improv_loop()
}
}

if (softAPmode && (millis() > 10 * 60 * 1000))
if (softAPmode && (millis64() > 10 * 60 * 1000))
{
RINFO("In Soft Access Point mode for over 10 minutes, reboot");
sync_and_restart();
return;
}

if (userConfig->wifiSettingsChanged && (millis() > wifiConnectTimeout))
if (userConfig->wifiSettingsChanged && (millis64() > wifiConnectTimeout))
{
bool connected = (WiFi.status() == WL_CONNECTED);
RINFO("30 seconds since WiFi settings change, connected to access point: %s", (connected) ? "true" : "false");
Expand All @@ -258,7 +258,7 @@ void improv_loop()
WiFi.setPhyMode((WiFiPhyMode_t)0);
write_config_to_file();
// Now try and reconnect...
wifiConnectTimeout = millis() + 30000;
wifiConnectTimeout = millis64() + 30000;
WiFi.reconnect();
return;
}
Expand All @@ -275,7 +275,7 @@ void improv_loop()
ip.fromString("0.0.0.0");
WiFi.config(ip, ip, ip);
// Now try and reconnect...
wifiConnectTimeout = millis() + 30000;
wifiConnectTimeout = millis64() + 30000;
WiFi.reconnect();
return;
} else {
Expand Down

0 comments on commit 638ebe3

Please sign in to comment.