Added one-wire thread and some old state table macro's. The state machine first state scans new one-wire devices and stores them in a linked list.

Tue, 02 Apr 2024 15:03:12 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 02 Apr 2024 15:03:12 +0200
changeset 654
e981d0185485
parent 653
6c4c884be155
child 655
780cc08df263

Added one-wire thread and some old state table macro's. The state machine first state scans new one-wire devices and stores them in a linked list.

MIGRATION file | annotate | diff | comparison | revisions
thermferm/Makefile file | annotate | diff | comparison | revisions
thermferm/devices.c file | annotate | diff | comparison | revisions
thermferm/devices.h file | annotate | diff | comparison | revisions
thermferm/one-wire.c file | annotate | diff | comparison | revisions
thermferm/one-wire.h file | annotate | diff | comparison | revisions
thermferm/statetbl.h file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
thermferm/thermferm.h file | annotate | diff | comparison | revisions
--- a/MIGRATION	Wed Mar 27 18:59:39 2024 +0100
+++ b/MIGRATION	Tue Apr 02 15:03:12 2024 +0200
@@ -41,3 +41,20 @@
 
 Add pigpio library and make it testable by the configure script.
 
+
+	Flow one-wire.
+	--------------
+
+States:
+  1. Init state.
+  2. Check for exit.
+     Scan for devices. Add to one-wire list.
+  3. Check for exit.
+     Read all DS2413 devices programmed as input.
+  4. Check for exit.
+     Read one temperture sensor from list and update device.
+  5. Check for exit.
+     Check for missing devices not in one wire table.
+     Goto 2.
+  6. Exit state.
+
--- a/thermferm/Makefile	Wed Mar 27 18:59:39 2024 +0100
+++ b/thermferm/Makefile	Tue Apr 02 15:03:12 2024 +0200
@@ -56,7 +56,8 @@
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
 mqtt.o: thermferm.h rdconfig.h devices.h xutil.h delay.h mqtt.h
-thermferm.o: lock.h rdconfig.h devices.h server.h thermferm.h delay.h simulator.h lcd-pcf8574.h lcd-buffer.h slcd.h panel.h futil.h xutil.h pid.h mqtt.h
+thermferm.o: lock.h rdconfig.h server.h thermferm.h devices.h delay.h simulator.h lcd-pcf8574.h lcd-buffer.h slcd.h panel.h one-wire.h futil.h xutil.h pid.h mqtt.h
+one-wire.o: thermferm.h statetbl.h one-wire.h xutil.h
 panel.o: thermferm.h delay.h lcd-pcf8574.h slcd.h panel.h
 devices.o: thermferm.h delay.h devices.h rc-switch.h panel.h xutil.h
 lcd-buffer.o: thermferm.h lcd-buffer.h lcd-pcf8574.h slcd.h panel.h
--- a/thermferm/devices.c	Wed Mar 27 18:59:39 2024 +0100
+++ b/thermferm/devices.c	Tue Apr 02 15:03:12 2024 +0200
@@ -504,7 +504,6 @@
 	}
 	closedir(fd);
     }
-    syslog(LOG_NOTICE, "%s", dhtaddr);
 
     if (dhtaddr) {
 
--- a/thermferm/devices.h	Wed Mar 27 18:59:39 2024 +0100
+++ b/thermferm/devices.h	Tue Apr 02 15:03:12 2024 +0200
@@ -1,9 +1,11 @@
 #ifndef MY_DEVICES_H
 #define	MY_DEVICES_H
 
+int read_w1(char *address, char *file);
+int write_w1(char *address, char *file, uint8_t val);
 
-int device_out(char *, int);
-int device_in(char *, int *);
+int device_out(char *uuid, int value);
+int device_in(char *uuid, int *value);
 int devices_detect(void);
 
 void *my_devices_loop(void *);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/one-wire.c	Tue Apr 02 15:03:12 2024 +0200
@@ -0,0 +1,191 @@
+/**
+ * @brief One-wire devices
+ *
+ * Copyright (C) 2024
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * mbsePi-apps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MBSE BBS; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "thermferm.h"
+#include "statetbl.h"
+#include "one-wire.h"
+#include "xutil.h"
+
+
+extern sys_config	Config;
+extern int		my_shutdown;
+extern pthread_mutex_t	mutexes[5];
+
+int			my_one_wire_state = 0;
+w1_list			*w1_devices = NULL;
+
+
+static int one_wire(void);
+
+void *my_one_wire_loop(void *threadid)
+{
+    my_one_wire_state = 1;
+    syslog(LOG_NOTICE, "Thread my_one_wire_loop started");
+
+    /*
+     * Run the state machine
+     */
+    one_wire();
+
+    /*
+     * Remove the dynamic tables.
+     */
+
+    syslog(LOG_NOTICE, "Thread my_one_wire_loop stopped");
+    my_one_wire_state = 0;
+    return 0;
+}
+
+
+
+
+SM_DECL(one_wire,(char *)"one-wire")
+SM_STATES
+    Scan,
+    Reading,
+    Missing
+SM_NAMES
+    (char *)"Scan",
+    (char *)"Reading",
+    (char *)"Missing"
+SM_EDECL
+
+    int			found, i;
+    FILE		*fp;
+//    devices_list	*device, *ndev;
+    w1_list		*dev_w1, *n_w1, *cur_w1 = NULL;
+    char		buffer[25], w1type[10];
+    uuid_t		uu;
+
+SM_START(Scan)
+
+SM_STATE(Scan)
+
+    if (my_shutdown) {
+	SM_SUCCESS;
+    }
+
+    /*
+     * Scan for current one-wire devices.
+     */
+    fp = fopen("/sys/devices/w1_bus_master1/w1_master_slaves", "r");
+    if (fp == NULL) {
+	syslog(LOG_NOTICE, "No w1_bus_master: %s", strerror(errno));
+	SM_ERROR;
+    }
+    while ((fgets(buffer, 25, fp))) {
+	buffer[strlen(buffer)-1] = '\0';
+//	syslog(LOG_NOTICE, "device %d %s", strlen(buffer), buffer);
+
+	strncpy(w1type, buffer, 2);
+	w1type[2] = '\0';
+
+	/*
+	 * Check if device is known and already detected.
+	 */
+	if ((strcmp(w1type, (char *)"3a") == 0) || (strcmp(w1type, (char *)"10") == 0) ||
+	    (strcmp(w1type, (char *)"22") == 0) || (strcmp(w1type, (char *)"28") == 0) ||
+	    (strcmp(w1type, (char *)"3b") == 0) || (strcmp(w1type, (char *)"42") == 0)) {
+	    found = FALSE;
+	    for (dev_w1 = w1_devices; dev_w1; dev_w1 = dev_w1->next) {
+		if (strcmp(dev_w1->address, buffer) == 0) {
+		    found = TRUE;
+		    dev_w1->timestamp = time(NULL);
+		    if (dev_w1->present != DEVPRESENT_YES) {
+			syslog(LOG_NOTICE, "One-wire device %s is back", buffer);
+			pthread_mutex_lock(&mutexes[LOCK_ONE_WIRE]);
+			dev_w1->present = DEVPRESENT_YES;
+			pthread_mutex_unlock(&mutexes[LOCK_ONE_WIRE]);
+		    }
+		    break;
+		}
+	    }
+	    if (found == FALSE) {
+		syslog(LOG_NOTICE, "One-wire device %s add new", buffer);
+		n_w1 = (w1_list *)malloc(sizeof(w1_list));
+		n_w1->next = NULL;
+		n_w1->address = xstrcpy(buffer);
+		strncpy(n_w1->family, buffer, 2);
+		n_w1->family[2] = '\0';
+		n_w1->present = DEVPRESENT_YES;
+		n_w1->subdevices = (strcmp(w1type, (char *)"3a") == 0) ? 2:1;
+		n_w1->timestamp = time(NULL);
+
+		pthread_mutex_lock(&mutexes[LOCK_ONE_WIRE]);
+		if (w1_devices == NULL) {
+		    w1_devices = n_w1;
+		    cur_w1 = w1_devices;	/* Point to first device	*/
+		} else {
+		    for (dev_w1 = w1_devices; dev_w1; dev_w1 = dev_w1->next) {
+			if (dev_w1->next == NULL) {
+			    dev_w1->next = n_w1;
+			    break;
+			}
+		    }
+		}
+		pthread_mutex_unlock(&mutexes[LOCK_ONE_WIRE]);
+	    }
+	} else {
+	    syslog(LOG_NOTICE, "One-wire device %d %s unknown", strlen(buffer), buffer);
+	}
+    }
+    fclose(fp);
+    SM_PROCEED(Reading);
+
+SM_STATE(Reading)
+
+    if (my_shutdown) {
+	SM_SUCCESS;
+    }
+
+    /*
+     * cur_w1 points to the next not handled device.
+     */
+    if (cur_w1 != NULL) {
+
+	syslog(LOG_NOTICE, "Reading %s", cur_w1->address);
+
+	sleep(1);
+
+	if (cur_w1->next != NULL) {
+	    cur_w1 = cur_w1->next;
+	} else {
+	    cur_w1 = w1_devices;
+	}
+
+    } else {
+    	sleep(1);
+    }
+
+    SM_PROCEED(Missing);
+
+SM_STATE(Missing)
+
+    if (my_shutdown) {
+	SM_SUCCESS;
+    }
+
+    sleep(1);
+    SM_PROCEED(Scan);
+
+SM_END
+SM_RETURN
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/one-wire.h	Tue Apr 02 15:03:12 2024 +0200
@@ -0,0 +1,11 @@
+/**
+ * @file one-wire.h
+ * @brief One-wire bus functions.
+ */
+
+#ifndef	ONE_WIRE_H
+#define	ONE_WIRE_H
+
+void *my_one_wire_loop(void *);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/statetbl.h	Tue Apr 02 15:03:12 2024 +0200
@@ -0,0 +1,57 @@
+/**
+ * @brief State table macro's
+ */
+
+#ifndef STATETBL_H
+#define STATETBL_H
+
+#define SM_DECL(proc,name) \
+int proc(void)\
+{\
+    int sm_success=0;\
+    char *sm_name=name;
+
+#define SM_STATES \
+    enum {
+
+#define SM_NAMES \
+    } sm_state; \
+    char * sm_sname[] = {
+
+#define SM_EDECL \
+    };
+
+#define SM_START(x) \
+    sm_state=x;\
+    syslog(LOG_NOTICE, "SM (%s): Start => %s", sm_name, sm_sname[sm_state]); \
+    while (!sm_success) switch (sm_state)\
+    {\
+    default: syslog(LOG_WARNING, "Statemachine %s error: state=%d",sm_name,sm_state);\
+    sm_success=-1;
+
+#define SM_STATE(x) \
+    break;\
+    case x:
+
+#define SM_END \
+    }\
+
+#define SM_RETURN \
+    return (sm_success != 1);\
+}
+
+#define SM_PROCEED(x) \
+    if (x != sm_state) {\
+	syslog(LOG_NOTICE, "SM (%s): %s => %s", sm_name, sm_sname[sm_state], sm_sname[x]);\
+    }\
+    sm_state=x; break;
+
+#define SM_SUCCESS \
+    syslog(LOG_NOTICE, "SM (%s): %s => Success", sm_name, sm_sname[sm_state]);\
+    sm_success=1; break;
+
+#define SM_ERROR \
+    syslog(LOG_WARNING, "SM (%s): %s => Error", sm_name, sm_sname[sm_state]);\
+    sm_success=-1; break;
+
+#endif
--- a/thermferm/thermferm.c	Wed Mar 27 18:59:39 2024 +0100
+++ b/thermferm/thermferm.c	Tue Apr 02 15:03:12 2024 +0200
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (C) 2014-2022
+ * Copyright (C) 2014-2024
  *   
  * Michiel Broek <mbroek at mbse dot eu>
  *
@@ -22,15 +22,16 @@
 
 #include "lock.h"
 #include "rdconfig.h"
-#include "devices.h"
 #include "server.h"
 #include "thermferm.h"
+#include "devices.h"
 #include "delay.h"
 #include "simulator.h"
 #include "lcd-pcf8574.h"
 #include "lcd-buffer.h"
 #include "slcd.h"
 #include "panel.h"
+#include "one-wire.h"
 #include "futil.h"
 #include "xutil.h"
 #include "pid.h"
@@ -51,6 +52,7 @@
 extern int		my_panel_state;
 extern int		my_server_state;
 extern int		my_simulator_state;
+extern int		my_one_wire_state;
 int			setupmenu = MENU_NONE;
 units_list		*current_unit = NULL;		/* In panel editor this points to the current unit. */
 float			temp_temp = 20.0;
@@ -1064,6 +1066,14 @@
 	t++;
     }
 
+    rc = pthread_create(&threads[t], NULL, my_one_wire_loop, (void *)t );
+    if (rc) {
+	fprintf(stderr, "my_one_wire_loop thread didn't start rc=%d\n", rc);
+	syslog(LOG_NOTICE, "my_one_wire_loop thread didn't start rc=%d", rc);
+    } else {
+	t++;
+    }
+
 #ifdef USE_SIMULATOR
     rc = pthread_create(&threads[t], NULL, my_simulator_loop, (void *)t );
     if (rc) {
@@ -1915,9 +1925,9 @@
 
     /*
      * Note that we don't care if the command server is stopped, this one
-     * does almost certain keep running but tat doesn't harm.
+     * does almost certain keep running but that doesn't harm.
      */
-    while ((my_devices_state + my_panel_state + my_simulator_state) > 0) { sleep(1); };
+    while ((my_devices_state + my_panel_state + my_simulator_state + my_one_wire_state) > 0) { sleep(1); };
     mqtt_disconnect();
 
     stopLCD();
--- a/thermferm/thermferm.h	Wed Mar 27 18:59:39 2024 +0100
+++ b/thermferm/thermferm.h	Tue Apr 02 15:03:12 2024 +0200
@@ -58,7 +58,7 @@
 #define	LOCK_DEVICES		0
 #define	LOCK_LCD		1
 #define	LOCK_MENU		2
-#define	LOCK_SPARE2		3
+#define	LOCK_ONE_WIRE		3
 #define	LOCK_SPARE3		4
 
 
@@ -304,6 +304,21 @@
 #define	DEVDIR_OUT_PWM		5		/* PWM outout			*/
 #define	DEVDIR_INTERN		6		/* Internal function		*/
 
+
+/*
+ * Dynamic one-wire devices list
+ */
+typedef struct _w1_list {
+    struct _w1_list		*next;
+    char			*address;	///< Device address
+    char			family[3];	///< Device family
+    int				present;	///< Present on bus
+    int				subdevices;	///< Number of subdevices
+    time_t			timestamp;	///< Last seen
+} w1_list;
+
+
+
 #ifdef USE_SIMULATOR
 
 /*

mercurial