374 Commits

Author SHA1 Message Date
Martin Preuss
b7234a6da2 start using new COM module in n27, r05 and t03. 2025-07-19 09:47:23 +02:00
Martin Preuss
4a5ba97b85 increase buffer size. 2025-07-19 09:46:06 +02:00
Martin Preuss
bdd710fc5c avr: started working on new SPI-like COM protocol.
use a clock and a data line to introduce synchronisation into the
protocol to be able to work with the wide range of mcu speeds (no need for
exact timing, no need for exact calibration).
2025-07-19 09:42:02 +02:00
Martin Preuss
535a695c50 limit number of loops inside main_runLoop. 2025-07-12 20:16:34 +02:00
Martin Preuss
357ffe4e17 comonuartX: handle multiple messages in one run.
still there are NOBUF errors...
2025-07-12 20:09:40 +02:00
Martin Preuss
349b4a929a use in instead of inr (SREG is always inside normal io space). 2025-07-12 20:08:54 +02:00
Martin Preuss
a06d245345 r05: disable OWI and ds18b20 modules (no time to handle those), increase buffers 2025-07-12 20:08:30 +02:00
Martin Preuss
83225c453d Use uid to determine initial wait time after re-enum request. 2025-07-12 20:07:33 +02:00
Martin Preuss
fa94190345 fixed message description for FLASH_DATA. 2025-07-12 00:22:18 +02:00
Martin Preuss
68aa3beab8 incremented firmware version. 2025-07-12 00:21:59 +02:00
Martin Preuss
3cd23d5f60 reduce size of net buffers from 32 to 28.
allows us to use 10 buffers in R05.
2025-07-12 00:21:47 +02:00
Martin Preuss
003f53b0b7 added READMEs 2025-07-11 23:25:19 +02:00
Martin Preuss
c1ea4212f2 Moved NET_BUFFERS_SIZE to network/defs.asm
- Changing this value requires changing the routine NET_Buffer_Locate
  so its best to keep both in one module.
- Redefining it in the individual devices doesn't change the code in
  NET_Buffer_Locate
2025-07-11 23:25:10 +02:00
Martin Preuss
3283a38981 Release 0.9.12. 2025-07-11 23:22:09 +02:00
Martin Preuss
3054274da5 Fixed stats value list. 2025-07-11 23:21:50 +02:00
Martin Preuss
2d84198e54 incremented version. 2025-07-07 21:53:59 +02:00
Martin Preuss
f3544f5e93 fixed apidoc. 2025-07-07 21:53:48 +02:00
Martin Preuss
04c02b5e33 fixed a bug. 2025-07-07 21:53:35 +02:00
Martin Preuss
b709b7e624 updated node doc. 2025-07-07 21:45:36 +02:00
Martin Preuss
8c397dd6b2 added missing includes. 2025-07-07 21:45:19 +02:00
Martin Preuss
6e923ce075 improved apidoc. 2025-07-07 21:44:54 +02:00
Martin Preuss
245d44c05d improved "run" code. 2025-07-07 21:44:40 +02:00
Martin Preuss
4f497fc41a removed unneeded code. 2025-07-07 21:43:41 +02:00
Martin Preuss
e32e8e7c13 use Eeprom_WriteByteIfChanged 2025-07-07 21:43:28 +02:00
Martin Preuss
f3020562bf incremented firmware version. 2025-07-07 16:06:31 +02:00
Martin Preuss
fbb710a4e3 added TLV code for EEPROM (not used for now). 2025-07-07 16:06:18 +02:00
Martin Preuss
cbd498150f avr: fully implemented router functionality in network and router app. 2025-07-07 16:05:53 +02:00
Martin Preuss
691ee3c71b incremented firmware version. 2025-07-06 20:22:38 +02:00
Martin Preuss
280d5828bf fixed a possible problem.
don't reboot on broadcast request.
2025-07-06 20:22:19 +02:00
Martin Preuss
6ecc1721b0 r05: no longer use APPS_NETWORK.
Implemented some of those features in APP_ROUTER like PING, REBOOT.
2025-07-06 20:21:51 +02:00
Martin Preuss
1824e8ccdf Increment packets-out counter. 2025-07-06 20:01:35 +02:00
Martin Preuss
0a45e38939 make router functionality of r05 an app. 2025-07-06 18:21:48 +02:00
Martin Preuss
81b008af0c r05, comOnUart0 and comOnUart1 work! 2025-07-06 17:19:59 +02:00
Martin Preuss
439e787d37 added values to device description file for t03. 2025-07-06 14:40:14 +02:00
Martin Preuss
d242d63c2e disable irqs when releasing buffer. 2025-07-06 14:39:48 +02:00
Martin Preuss
86982d0000 reuse code. 2025-07-06 14:39:16 +02:00
Martin Preuss
f549ef5d27 added debug output. 2025-07-06 14:39:02 +02:00
Martin Preuss
fe2eaafb7b add devices r04 and r05 to flash script. 2025-07-06 14:38:43 +02:00
Martin Preuss
caf149fe8b minor changes to unify modules. 2025-07-06 14:38:21 +02:00
Martin Preuss
c540135705 fixed a bug. 2025-07-06 14:37:10 +02:00
Martin Preuss
734c237666 sort counters to simplify stats app. 2025-07-06 14:36:50 +02:00
Martin Preuss
85d445ec61 t03: use comonuart0 from uart_hw2 2025-07-06 14:35:52 +02:00
Martin Preuss
b059f4a56e added node r05. 2025-07-06 14:35:22 +02:00
Martin Preuss
b56ab22117 more work on test firmware for r04 2025-07-06 14:34:55 +02:00
Martin Preuss
5bda393b10 added valueids for stats from 2nd network device. 2025-07-06 12:24:46 +02:00
Martin Preuss
4ad508eca6 n27: removed driver for SGP30 (is now used externally in n26). 2025-07-06 12:23:49 +02:00
Martin Preuss
7f856dacf6 use uart_hw2 now. 2025-07-06 12:22:50 +02:00
Martin Preuss
b6ba56a564 added code to read calibration data. 2025-07-06 12:22:22 +02:00
Martin Preuss
f930b846c2 uart_hw2: basically works, but skips messages. 2025-07-06 12:21:41 +02:00
Martin Preuss
fc5394a5c9 avr: added comonuart0
works fine so far.
2025-07-03 22:12:40 +02:00
Martin Preuss
725ff96425 added test firmware for r04. 2025-07-03 22:11:27 +02:00
Martin Preuss
bfd0cd77a9 comonuart1: fixed bit names, disable IRQ when starting to write. 2025-07-03 00:16:29 +02:00
Martin Preuss
548a7634b7 comonuart1: undid some of the latest changes. 2025-07-02 00:10:46 +02:00
Martin Preuss
3e4637e174 comonuart1: try to solve timing/irq problem. 2025-07-02 00:08:01 +02:00
Martin Preuss
20b7c3f50d avr: new uart_hw2 module comonuart1 works now. 2025-07-01 00:52:44 +02:00
Martin Preuss
9206341032 started working on improved UART_HW module. 2025-06-30 21:29:05 +02:00
Martin Preuss
6383d18e0e avr: added comonuart1. 2025-06-29 22:32:43 +02:00
Martin Preuss
cfc7dc6320 avr: added r04. 2025-06-29 22:31:51 +02:00
Martin Preuss
72acef3aaf Increased max message size. 2025-06-26 00:31:11 +02:00
Martin Preuss
850975a85b avr: fixed a bug (was not calling sysOnEveryDay) 2025-06-26 00:18:33 +02:00
Martin Preuss
68ee246216 aqhome-tool: added some commands
- getFirstData
- getLastData
- getPeriodData
2025-06-26 00:18:05 +02:00
Martin Preuss
2ba802bb06 More work on dataclient library. 2025-06-26 00:16:52 +02:00
Martin Preuss
688129cf08 added n27 to flash script. 2025-06-25 00:09:41 +02:00
Martin Preuss
81721ab7eb avr: added device n27. 2025-06-25 00:05:47 +02:00
Martin Preuss
bf50871208 n25: use pin PA5 to select led strip driver to use
does nothing for now but will later allow to select between SK6812 and SPI.
2025-06-25 00:05:19 +02:00
Martin Preuss
cbf88e05fe added "mode" argument to "getdata" command. 2025-06-25 00:03:58 +02:00
Martin Preuss
a808450fa2 add dataclient sublib to be used by multiple tools. 2025-06-25 00:03:09 +02:00
Martin Preuss
033b7cd4db getvalues: allow for filtering value list on server. 2025-06-25 00:02:32 +02:00
Martin Preuss
cd6a918533 s_getvalues: allow for filtering output list. 2025-06-25 00:01:52 +02:00
Martin Preuss
63ebcbadc9 added msg "getValues" 2025-06-25 00:01:12 +02:00
Martin Preuss
b2802a37aa added AQH_Storage_GetFirstNDataPoints() 2025-06-25 00:00:39 +02:00
Martin Preuss
1e95b317bf incremented firmware version. 2025-06-23 19:28:35 +02:00
Martin Preuss
78fec171f9 sgp30: measure every second, increases accuracy. 2025-06-23 19:28:20 +02:00
Martin Preuss
8bfaabcf27 read 10bit brightness (instead of 8 bit). 2025-06-23 19:27:53 +02:00
Martin Preuss
2b08847cf7 added n26. 2025-06-23 19:21:58 +02:00
Martin Preuss
9ea722607f avr: added brightness sensor 2025-06-23 19:21:49 +02:00
Martin Preuss
409155f0d0 increment version. 2025-06-17 00:14:14 +02:00
Martin Preuss
026a943648 avr: adde stats messages to device definitions. 2025-06-17 00:13:52 +02:00
Martin Preuss
aeb6df5685 avr: reduce number of messages send.
- sensor report interval 60->120s
- stats report interval 11-31 mins
2025-06-17 00:13:33 +02:00
Martin Preuss
06886e0094 aqhome-cgi: more work 2025-06-16 23:31:53 +02:00
Martin Preuss
b498a445b2 added missing files, n26, increased firmware version. 2025-06-16 23:31:38 +02:00
Martin Preuss
876e9ac7b9 avr: added n14 back in. 2025-06-16 23:29:56 +02:00
Martin Preuss
a89b875872 avr: added NET_Interface_ResetStats and call it daily. 2025-06-16 23:29:18 +02:00
Martin Preuss
0ce70e48b1 avr: added type "light" 2025-06-16 23:27:37 +02:00
Martin Preuss
bf583a1aa5 avr: incremented version. 2025-06-15 17:47:45 +02:00
Martin Preuss
1533f82ec4 n21: send value of door sensor every minute
this will allow us to determine the best value for a adc limit to detect
open/closed windows and doors.
2025-06-15 17:47:34 +02:00
Martin Preuss
8a43bc252f tcrt1000: decreased limit from 170 to 100 2025-06-15 17:46:06 +02:00
Martin Preuss
ffcc5c0d9f some minor work on gui/win modules. 2025-06-12 23:30:36 +02:00
Martin Preuss
c51043d72a more work on aqhome-cgi. 2025-06-12 23:30:08 +02:00
Martin Preuss
2cb534df85 more work on GUI module. 2025-06-05 22:48:22 +02:00
Martin Preuss
4f30623f2d increased stacksize. 2025-06-05 22:47:54 +02:00
Martin Preuss
b9ac7c65fa include CCS811 in reportsensors app. 2025-06-05 22:46:55 +02:00
Martin Preuss
cef487fb3a re-enabled node n19. adapted n20. 2025-06-05 22:45:52 +02:00
Martin Preuss
284539fd52 re-enabled CCS811 module, adapted to latest changes. 2025-06-05 22:44:27 +02:00
Martin Preuss
08a1313ba5 More work on layout code. 2025-06-04 23:56:42 +02:00
Martin Preuss
7349014bd6 Make coordinates 16 bit again. 2025-06-04 23:56:29 +02:00
Martin Preuss
12cfe2ff4b Fixed a bug.
Need to make room for stack.
2025-06-04 23:56:04 +02:00
Martin Preuss
ae1892f196 share code. 2025-06-03 00:00:14 +02:00
Martin Preuss
dbad237826 fixed a typo. 2025-06-02 23:41:38 +02:00
Martin Preuss
56e222a97e split WID_SIGNAL_GETMINSIZE into two signals. 2025-06-02 23:38:08 +02:00
Martin Preuss
888792a201 more work on gui code. 2025-06-02 23:29:50 +02:00
Martin Preuss
41867ed01a added missing files. 2025-06-02 23:29:06 +02:00
Martin Preuss
b82e0d02df avr: more general approach to fonts. 2025-06-02 21:13:44 +02:00
Martin Preuss
cd1fce313e avr: added some unit tests for LIST and TREE. 2025-06-02 21:13:01 +02:00
Martin Preuss
5153bd2f69 removed signal "CREATED".
unsure when this would be called:
- when the basic object is called?
- when the last derived object is called?
better remove it to avoid complications...
2025-06-02 01:04:49 +02:00
Martin Preuss
d4ad6844e3 ili9341: save X 2025-06-02 01:03:23 +02:00
Martin Preuss
4f610c68a2 added more fonts and corresponding code. disabled test code in ili9341 module. 2025-06-02 01:03:03 +02:00
Martin Preuss
3582659018 added more bigcall/bigjmp as we go along with larger code. 2025-06-02 01:02:06 +02:00
Martin Preuss
1f537849a9 incremented version. 2025-06-01 22:39:56 +02:00
Martin Preuss
e6d0118ff3 n25: fixed interrupt table (was still for t85!). 2025-06-01 22:38:48 +02:00
Martin Preuss
ff7d47e155 avr: adapted to latest changes. 2025-06-01 22:38:17 +02:00
Martin Preuss
8ae50a8d60 fixed flashnode.sh for n24, added n25 2025-06-01 22:37:46 +02:00
Martin Preuss
08411d9430 NET_IFACE_OFFS_HANDLED_LOW no longer exists. 2025-06-01 22:37:26 +02:00
Martin Preuss
9bd3182bd5 simplified timer and sleep setup code for AtTiny84. 2025-06-01 22:36:59 +02:00
Martin Preuss
c45eb6cca2 fixed blinkled fn: always switch LED port to output. 2025-06-01 22:36:26 +02:00
Martin Preuss
b229b39ab8 c02: started working on AtMEGA 644P based node. 2025-06-01 19:26:31 +02:00
Martin Preuss
87b5e01581 add missing include. 2025-06-01 19:25:57 +02:00
Martin Preuss
8188f33345 uart_bitbang2: introduced macros for ATTN irq setup. 2025-06-01 19:25:47 +02:00
Martin Preuss
7403b6650b n24: include common/calls.asm 2025-06-01 19:25:16 +02:00
Martin Preuss
6bbf2ba788 c01: use UART_BitBang_PcintIsr 2025-06-01 19:24:49 +02:00
Martin Preuss
06b0ed8551 c01: fixed include. 2025-06-01 19:24:13 +02:00
Martin Preuss
ada19028e0 dont use old constant. 2025-06-01 19:23:38 +02:00
Martin Preuss
1e5de0da23 flash: use 16-bit counters. 2025-06-01 19:22:04 +02:00
Martin Preuss
bb14dd4c22 introduce macros bigjmp and bigcall for intermodule calls/jmps
translates to rjmp/rcall on MCUs with up to 8K flash and to jmp/call
on others.
2025-06-01 19:18:25 +02:00
Martin Preuss
188e7da379 incremented firmware version. 2025-06-01 00:21:52 +02:00
Martin Preuss
982c9bd649 re-enable some modules and apps on n20. 2025-06-01 00:21:37 +02:00
Martin Preuss
fec37bd221 disable debug code. 2025-06-01 00:21:21 +02:00
Martin Preuss
120e3e1e6b uart bitbang2 now also works on c01! 2025-06-01 00:21:07 +02:00
Martin Preuss
8d1661d8e4 improved output from "getdevices" command. 2025-06-01 00:20:28 +02:00
Martin Preuss
18f61f4d63 added include for debug functions (commented-out). 2025-05-31 15:37:31 +02:00
Martin Preuss
be74442e7f receiving works again. 2025-05-31 15:36:52 +02:00
Martin Preuss
061119819f sending works again with n20. 2025-05-31 14:20:05 +02:00
Martin Preuss
0b8cb929b7 split uart_bitbang2 into multiple files. 2025-05-30 17:03:35 +02:00
Martin Preuss
f1c858e3a7 Use n20 for bugfixing. 2025-05-30 15:25:42 +02:00
Martin Preuss
3fc7eff424 add n20. 2025-05-29 22:54:25 +02:00
Martin Preuss
36050b14c5 wait for one bitlength between bytes. disable collision detection. 2025-05-29 21:04:30 +02:00
Martin Preuss
fa6acd8e52 added aqua_n25.xml 2025-05-29 20:27:07 +02:00
Martin Preuss
dbf7f76baa moved versions to a dedicated file shared by all nodes. 2025-05-29 20:26:43 +02:00
Martin Preuss
18be337160 minor change 2025-05-29 20:25:49 +02:00
Martin Preuss
0bd6ef8db4 fix defs for n24. 2025-05-29 20:25:34 +02:00
Martin Preuss
7fb1722c70 added missing .include 2025-05-29 20:25:07 +02:00
Martin Preuss
279d92e338 prepared removal of defs_all.asm 2025-05-29 20:24:41 +02:00
Martin Preuss
a26dd6f2a5 added stats vars to n21 2025-05-29 20:24:13 +02:00
Martin Preuss
785e4ef28c added n16 2025-05-29 20:23:53 +02:00
Martin Preuss
dff347bcb7 created pong message. 2025-05-29 20:23:44 +02:00
Martin Preuss
619ac1564e debug: send rxstats every minute. 2025-05-29 20:20:43 +02:00
Martin Preuss
581eeff996 apps/network: implemented ping request. 2025-05-29 15:47:21 +02:00
Martin Preuss
b4e747c3db added header. 2025-05-29 15:44:30 +02:00
Martin Preuss
04dec73988 added device n25 2025-05-29 15:43:33 +02:00
Martin Preuss
af75532ba7 More planning on GUI. 2025-05-28 19:03:14 +02:00
Martin Preuss
335163f887 temporarily disabled writing text on startup (need the flash space). 2025-05-28 00:52:40 +02:00
Martin Preuss
b3274466a3 smaller changes to make debugging easier. 2025-05-28 00:52:06 +02:00
Martin Preuss
064e84f5e8 added a more compact uart module. 2025-05-28 00:51:37 +02:00
Martin Preuss
18bc231951 added some test code. 2025-05-28 00:51:07 +02:00
Martin Preuss
9a19bf739d fixed a bug (wrong register). 2025-05-28 00:50:52 +02:00
Martin Preuss
9e6feecb88 bootloader: decreased waiting times for LED blinking on bootup. 2025-05-28 00:50:26 +02:00
Martin Preuss
baf77ed182 fixed defs file. 2025-05-28 00:49:44 +02:00
Martin Preuss
b2f7232422 c01: use alternative uart module. 2025-05-28 00:49:28 +02:00
Martin Preuss
961568f721 renamed makros M_IO_READ and M_IO_WRITE to inr and outr 2025-05-28 00:49:07 +02:00
Martin Preuss
042db13994 avr/apps/stats: send VALUE_REPORT messages instead of individual stats messages.
this makes it easier to add some more stats later and it removes some
messages.
2025-05-28 00:47:19 +02:00
Martin Preuss
ba434d88a2 improved output. 2025-05-28 00:45:10 +02:00
Martin Preuss
d32e2f4b81 handle stats values in nodes server. added missing code. 2025-05-28 00:44:58 +02:00
Martin Preuss
e40139fee2 add missing files. 2025-05-26 21:41:41 +02:00
Martin Preuss
d8612a01ca adapted to latest changes. 2025-05-26 21:41:30 +02:00
Martin Preuss
474e63c395 fixed documentation. 2025-05-26 21:40:45 +02:00
Martin Preuss
ceaeb756fb let old file include new files. 2025-05-26 21:40:28 +02:00
Martin Preuss
603a8e93d0 avr/flash: removed unnecessary code. 2025-05-26 21:10:12 +02:00
Martin Preuss
4fdfd77a54 put wait routines into their own files.
helps with reducing size of bootloader.
2025-05-26 21:09:45 +02:00
Martin Preuss
6b5f5e877d avr/heap: fixed some bugs. 2025-05-24 21:01:59 +02:00
Martin Preuss
77bb64fbb6 Merge branch 'mp-2025_05-uart2' 2025-05-24 17:49:44 +02:00
Martin Preuss
92d5e30f3c t03: message forwarding is now much faster.
this is very visible when flashing firmware to nodes via t03 device.
2025-05-24 17:49:01 +02:00
Martin Preuss
349c11d641 reset uart_hw code to what works on t03. 2025-05-24 17:45:33 +02:00
Martin Preuss
027edb9aba removed waiting time between sending messages.
now a message can be send after every interrupt.
2025-05-24 17:26:59 +02:00
Martin Preuss
868c2b32f8 Revert "allow for private tick counter and special timer frequencies."
This reverts commit 3e9aeeed05.
2025-05-24 17:25:24 +02:00
Martin Preuss
2acd25e805 added README. 2025-05-24 17:25:14 +02:00
Martin Preuss
b730fd068c fixed apidoc. 2025-05-24 17:25:00 +02:00
Martin Preuss
3e9aeeed05 allow for private tick counter and special timer frequencies. 2025-05-24 17:24:46 +02:00
Martin Preuss
158cf994c5 fixed a bug on t841. 2025-05-24 17:24:00 +02:00
Martin Preuss
391c06e7e5 avr: more work on fonts, added heap functions. 2025-05-24 15:32:45 +02:00
Martin Preuss
fa5acddcbe avr: started working on prerequisites for a window gui system. 2025-05-22 23:19:33 +02:00
Martin Preuss
7d233136eb moved graphops into a dedicated sourcefile. 2025-05-22 16:29:55 +02:00
Martin Preuss
a4975038b4 more generalisation of font code. 2025-05-22 15:57:03 +02:00
Martin Preuss
229e68077c ili9341: moved text functions to dedicated source file. 2025-05-22 01:19:04 +02:00
Martin Preuss
143180d68b ili9341: added bitblit routines. 2025-05-22 00:42:55 +02:00
Martin Preuss
c065415713 ili9341: created dedicated sourcefile for font handling. 2025-05-22 00:42:18 +02:00
Martin Preuss
b01e8ff004 ili9341: first ideas for window/screen management. 2025-05-21 01:45:02 +02:00
Martin Preuss
de94590fa0 ili9341: moved io code into own file. changed args to r0-r11. 2025-05-21 01:44:38 +02:00
Martin Preuss
b3d7d492d7 ili9341: added routine to write a char in double height/width. 2025-05-21 00:12:38 +02:00
Martin Preuss
d29147fe57 added ili9341_WriteCharacterAt. 2025-05-20 23:36:31 +02:00
Martin Preuss
a0898b8327 insert 2 bytes at beginning of a font (first char, num chars) 2025-05-20 23:36:00 +02:00
Martin Preuss
2ca246deca removed ili9341WriteColorTable 2025-05-20 21:32:53 +02:00
Martin Preuss
c1d347b70b started working with fonts. 2025-05-20 21:32:18 +02:00
Martin Preuss
381afa97f4 ili9341: finalized SPI params. 2025-05-20 21:32:04 +02:00
Martin Preuss
cb379d4149 avr: started working on new LCD module and SPI module. 2025-05-20 00:31:56 +02:00
Martin Preuss
aceffdfad2 uart_hw: removed unneeded code. 2025-05-20 00:31:12 +02:00
Martin Preuss
8ece026f2d Add wait routines for milliseconds. 2025-05-20 00:29:45 +02:00
Martin Preuss
d000c8621e increased buffer size. 2025-05-18 01:04:15 +02:00
Martin Preuss
cf1eba68f0 try new implementation of UART code for m8515. 2025-05-18 00:59:19 +02:00
Martin Preuss
b6800e538d tried some fixes... 2025-05-18 00:58:46 +02:00
Martin Preuss
b8fbbb7125 remove COM_* code. 2025-05-18 00:58:11 +02:00
Martin Preuss
4b4753415a sort order of stats messages. 2025-05-18 00:57:03 +02:00
Martin Preuss
1c053d0492 fixed apidoc. 2025-05-18 00:56:43 +02:00
Martin Preuss
44b8848996 minor beautifications. 2025-05-17 14:24:23 +02:00
Martin Preuss
550967c176 memstats: send XRAM size instead of stack size. 2025-05-17 14:24:04 +02:00
Martin Preuss
e713711a61 added missing includes. 2025-05-17 14:23:34 +02:00
Martin Preuss
613a7e629d remove unneeded includes. 2025-05-17 14:23:24 +02:00
Martin Preuss
5026a7b753 c01: use modules CLOCK and XRAM. 2025-05-17 14:23:10 +02:00
Martin Preuss
75b602811c added XRAM module.
Module for external SRAM with AtMega8515.
2025-05-17 14:22:49 +02:00
Martin Preuss
2897aece2c added memory stats. 2025-05-17 14:22:05 +02:00
Martin Preuss
2cc260790c c01: removed unneeded code. 2025-05-17 13:21:07 +02:00
Martin Preuss
1ac4b8cad0 c01: enable more modules and apps. 2025-05-17 13:20:51 +02:00
Martin Preuss
ab3b2be725 consequently use M_IO_READ and M_IO_WRITE.
on tn841 those are in the extended io space, on most others in normal
io space.
2025-05-17 13:19:54 +02:00
Martin Preuss
10e4aa8f85 fixed a problem with m8515 UART.
UBRRH and UCSRC share the same io register location, bit URSEL needs to
be set in order to access UCSRC!!
2025-05-17 13:18:50 +02:00
Martin Preuss
ea0d426430 added definition for bit USBS 2025-05-17 13:17:16 +02:00
Martin Preuss
27a0214b5d removed old COM2 parts from code. 2025-05-17 13:16:46 +02:00
Martin Preuss
f9cd1833da Merge branch 'master' into mp-2025_05-mega8515 2025-05-17 10:51:54 +02:00
Martin Preuss
f8d3d09716 n21: fixed README. 2025-05-17 10:51:21 +02:00
Martin Preuss
484a455df7 t03: use new uart file. 2025-05-17 10:51:04 +02:00
Martin Preuss
21c2c60f4f started working on AtMega8515 module C1. 2025-05-17 10:50:09 +02:00
Martin Preuss
5a46db37c1 bootloader: decreased waiting time. 2025-05-17 10:49:03 +02:00
Martin Preuss
e545251b27 moved timer setup code into hardware include file. 2025-05-17 10:48:39 +02:00
Martin Preuss
d51ca9b1d1 n21: added VALUE_ID_LEDSIMPLE_TIMING 2025-05-17 10:47:59 +02:00
Martin Preuss
dba503df5b only call LedSimple_OnPacketReceived is networking code enabled. 2025-05-17 10:47:44 +02:00
Martin Preuss
732dcd74f7 only include "sendvalue.asm" if networking code enabled. 2025-05-17 10:47:29 +02:00
Martin Preuss
930229b969 add macros for reading/writing IO regs regardless of their position (i.e. < or >=0x40). 2025-05-17 10:46:46 +02:00
Martin Preuss
bb4e16cae7 add line with ATTN. 2025-05-17 10:46:03 +02:00
Martin Preuss
f5606554c9 added tool flashnode.sh 2025-05-17 10:45:37 +02:00
Martin Preuss
d97d2ac08f fixed a bug. 2025-05-17 10:44:48 +02:00
Martin Preuss
f834a4ecc5 fixed apidoc. 2025-05-17 10:44:37 +02:00
Martin Preuss
92b7d1bb13 valsched: only repeat values in first loop. 2025-05-15 00:58:54 +02:00
Martin Preuss
b775c9b6b2 n23/n24: improved handling of some values. Removed old files. 2025-05-15 00:34:57 +02:00
Martin Preuss
63acb95834 started working on node n24. 2025-05-14 23:20:16 +02:00
Martin Preuss
faa46c7e38 added modules for SGP30/40. 2025-05-14 23:18:26 +02:00
Martin Preuss
fee3606a61 added "LEDTIMING" value. 2025-05-14 01:51:17 +02:00
Martin Preuss
92bcd366cb add functions to remotely set LED timing. 2025-05-14 01:50:59 +02:00
Martin Preuss
bc54f5bda1 fixed a bug. 2025-05-14 01:50:34 +02:00
Martin Preuss
30945807d8 minor changes. 2025-05-14 01:50:23 +02:00
Martin Preuss
95a0e6ea9d Reserve bytes in EEPROM. 2025-05-14 01:49:42 +02:00
Martin Preuss
47275556f9 allow for remotely setting LED timing. 2025-05-14 01:49:23 +02:00
Martin Preuss
25fb6f262d fixed a bug. 2025-05-14 01:48:40 +02:00
Martin Preuss
147f920eb6 avr/sk6812: improved protocol implementation.
still doesn't work with new 5m LED strips from BTF-Lighting (1m strips
do work, as do older 5m stripes).
2025-05-14 01:48:24 +02:00
Martin Preuss
b63d625d12 Log all messages. 2025-05-14 01:46:43 +02:00
Martin Preuss
11657cef75 added missing file. 2025-05-10 15:18:43 +02:00
Martin Preuss
5dd0e6fd95 add "-N" to aqhome-nodes.service 2025-05-10 15:17:57 +02:00
Martin Preuss
9a993445c4 adapted n16 to latest changes. 2025-05-10 15:17:35 +02:00
Martin Preuss
4baa949a77 moved multiplication function to "common" dir, added divide routine. 2025-05-10 15:17:08 +02:00
Martin Preuss
c7823d3874 added "-N" 2025-05-10 15:15:05 +02:00
Martin Preuss
074a7e5650 cleanup build system. 2025-05-08 17:59:27 +02:00
Martin Preuss
64e2cf5d25 avr/devices/all: started integrating code from t03. 2025-05-08 17:14:33 +02:00
Martin Preuss
cc7ef0cf30 flash: wait for ATTN high before waiting for message.
this helps with syncing.
2025-05-07 20:03:58 +02:00
Martin Preuss
9102d90c34 flash: minor timing change. 2025-05-07 20:03:06 +02:00
Martin Preuss
6832487c46 flash: fixed a bug (reversed register order). 2025-05-07 20:02:42 +02:00
Martin Preuss
f5cf85a931 flash: reduced waiting times. 2025-05-07 20:02:07 +02:00
Martin Preuss
d57d721dbf flash: increased number of retries when waiting for FLASH_DATA msg. 2025-05-07 20:01:34 +02:00
Martin Preuss
aa97197413 added missing include. 2025-05-07 20:00:58 +02:00
Martin Preuss
d7df84549b Fixed a typo. 2025-05-07 20:00:42 +02:00
Martin Preuss
8feb8982c1 added README. 2025-05-07 20:00:27 +02:00
Martin Preuss
f4acc829f7 avr/devices/n21: removed unneeded definitions. 2025-05-05 21:06:07 +02:00
Martin Preuss
34b2fe4007 avr/devices/n23: add missing include. 2025-05-05 21:05:49 +02:00
Martin Preuss
72f52da17b avr/modules/sk6812: uncomment unused code. 2025-05-05 21:05:30 +02:00
Martin Preuss
eecb022a0c avr/modules/flash: make protocol more robust
- wait for ATTN high after error receiving a packet
- use different wait times when waiting for FLASH_START and FLASH_DATA
2025-05-05 21:05:07 +02:00
Martin Preuss
9063962c7d avr/apps/ma_light: adapted to latest changes. works now. 2025-05-05 21:03:13 +02:00
Martin Preuss
9e25cbb183 apps/aqhome-tool/flash: shorten re-send time 2025-05-05 21:02:17 +02:00
Martin Preuss
9af57eaac0 sk6812: don't pull DIN high (sometimes modifies first LED). 2025-05-05 01:20:30 +02:00
Martin Preuss
f31567e785 sk6812: send RESET to led strip at start. 2025-05-04 22:42:42 +02:00
Martin Preuss
dc62f1fe05 added mising file. 2025-05-04 22:42:11 +02:00
Martin Preuss
868268d116 t03: adapted to latest changes. 2025-05-04 03:38:41 +02:00
Martin Preuss
9f663b0ed9 n21, n23: increase buffer size to 32 (otherwise value messages might not fit). 2025-05-04 03:38:09 +02:00
Martin Preuss
827497bb5e minor format change. 2025-05-04 03:37:22 +02:00
Martin Preuss
688f02df47 re-add n22. 2025-05-04 03:36:56 +02:00
Martin Preuss
33ec6d0a67 fixed apidoc. 2025-05-04 03:36:13 +02:00
Martin Preuss
b3f19b0432 add additional waitstate after acquiting bus. 2025-05-04 03:35:59 +02:00
Martin Preuss
e6ea506a74 sk6812 now works again (at least with 1m LEDs). 2025-05-04 03:35:28 +02:00
Martin Preuss
2ac090cf14 some fixes. 2025-05-04 03:34:48 +02:00
Martin Preuss
46b24bf442 avr/modules/network: disable interrupts on alloc/release. 2025-05-04 03:34:11 +02:00
Martin Preuss
9a854977a4 avr: more work on basic device code. 2025-05-04 03:33:32 +02:00
Martin Preuss
e25b0ad69d avr/module/flash: unified flash code for 1p/4p devices.
AtTiny 841 erases 4 pages at once, others only erase one.
Fixed a bug: only send ONE flash response to FLASH_START!!!
2025-05-04 03:32:53 +02:00
Martin Preuss
b632a10fff avr/apps: added ma_light (was previously a module). 2025-05-04 03:30:55 +02:00
Martin Preuss
e20b1c52d3 increased verbosity. 2025-05-04 03:30:28 +02:00
Martin Preuss
08e1428902 avr: adapted n23 to latest changes. 2025-05-01 01:01:22 +02:00
Martin Preuss
5f220dc86f avr: adapted n21 to latest changes. 2025-05-01 01:01:05 +02:00
Martin Preuss
51d32dc505 avr: move SK6812_OnPacketReceived to dedicated file. 2025-05-01 00:59:02 +02:00
Martin Preuss
048eccf4c6 avr: toggle LED while waiting for ATTN line. 2025-05-01 00:58:32 +02:00
Martin Preuss
9e37ebb261 avr: adapted to latest changes. 2025-05-01 00:58:14 +02:00
Martin Preuss
de89bc94b6 avr: use 2 byte counter for f_keepup. 2025-05-01 00:57:48 +02:00
Martin Preuss
ab9c177793 avr: adapted ds18b20 module to latest changes. 2025-05-01 00:57:22 +02:00
Martin Preuss
6ce1aac1d7 avr: rename routines to call internal ones instead of directly calling into the main app. 2025-05-01 00:56:40 +02:00
Martin Preuss
e56f2600e8 avr: more work on avr app framework. 2025-05-01 00:56:03 +02:00
Martin Preuss
614a30fd4e avr: generate new uid if the current one consists of 4 equal bytes. 2025-05-01 00:55:33 +02:00
Martin Preuss
5981ec44e4 avr: only write COM address if changed to reduce EEPROM wear. 2025-05-01 00:54:48 +02:00
Martin Preuss
8008819989 avr: added apps and missing files. 2025-05-01 00:53:29 +02:00
Martin Preuss
7edaed601b fixed a typo. 2025-05-01 00:52:48 +02:00
Martin Preuss
06434512c7 avr: added new version of tcrt1000. 2025-04-29 00:37:31 +02:00
Martin Preuss
fa65bc53b5 avr: added new version of driver for si7021. 2025-04-29 00:37:01 +02:00
Martin Preuss
c1a67a36ef avr/modules/network: added messages. 2025-04-29 00:36:20 +02:00
Martin Preuss
1e90682605 avr: use new code in latest nodes. 2025-04-29 00:35:45 +02:00
Martin Preuss
2357b63b42 added initial wait routine. 2025-04-29 00:34:53 +02:00
Martin Preuss
e1b2650221 avr: added apps and use them in multiple nodes. 2025-04-29 00:34:24 +02:00
Martin Preuss
52ae473ad1 aqhome-tool: no longer expect a reboot response. 2025-04-29 00:32:59 +02:00
Martin Preuss
833819f713 network: write new address into EEPROM. 2025-04-26 11:10:23 +02:00
Martin Preuss
155fc9a743 uart_bitbang2: use new constants. 2025-04-26 11:07:31 +02:00
Martin Preuss
a03fc012f4 uart_bitbang2: hardcoded interface data. 2025-04-26 11:07:15 +02:00
Martin Preuss
5b93d58309 tcrt1000: started simplified version of driver.
message sending/timing/signal shaping is now done externally in the filter
modules so that they can be reused by multiple drivers.
2025-04-26 11:06:25 +02:00
Martin Preuss
bef677eda4 valsched: use cbr and sbr. 2025-04-26 11:05:27 +02:00
Martin Preuss
265a1e6043 si7021: started simplifyied version of driver. 2025-04-26 11:05:07 +02:00
Martin Preuss
b21c111aa3 network: fixed vars. 2025-04-26 11:04:41 +02:00
Martin Preuss
b9419520f4 network: removed duplicate code. 2025-04-26 11:04:28 +02:00
Martin Preuss
8925ce23e9 N23 basically works now. 2025-04-26 11:04:01 +02:00
Martin Preuss
feabc76e36 started working on new n23 code. 2025-04-21 00:47:27 +02:00
Martin Preuss
f806cf30e5 Revert "added ifdefs guards for includes."
This reverts commit 15199a17a5.
2025-04-21 00:46:57 +02:00
Martin Preuss
15199a17a5 added ifdefs guards for includes. 2025-04-21 00:46:46 +02:00
Martin Preuss
30654509b1 added uart_bitbang2. 2025-04-21 00:45:59 +02:00
Martin Preuss
ea2162e8f4 added filter. 2025-04-21 00:44:04 +02:00
Martin Preuss
ebba98ef16 si7021: honour PRESENT flag, added GetValue 2025-04-21 00:43:50 +02:00
Martin Preuss
b995f1c3fb added more messages. 2025-04-21 00:43:11 +02:00
Martin Preuss
77e573192e more work on network interface. 2025-04-21 00:39:19 +02:00
Martin Preuss
ba55a2898d started working on 2nd version of motion module. 2025-04-21 00:36:45 +02:00
Martin Preuss
16a6bb08b5 fixed return values. 2025-04-21 00:36:07 +02:00
Martin Preuss
b2a087c959 added debug code. 2025-04-21 00:33:52 +02:00
Martin Preuss
7349dcba8d flash: fixed wait times etc. 2025-04-21 00:32:59 +02:00
Martin Preuss
e4145afbfe added filter modules. 2025-04-21 00:32:30 +02:00
Martin Preuss
876d1cad0e added module "clock" 2025-04-21 00:32:00 +02:00
Martin Preuss
eea0a66b84 aqhome-react: fixed unit timeprogram. 2025-04-21 00:29:53 +02:00
Martin Preuss
b4d71a0fad added app aqhome-cgi. 2025-04-21 00:29:31 +02:00
Martin Preuss
89542e06c9 avr: consolidated uart_hw module 2025-03-27 00:20:58 +01:00
Martin Preuss
3555b49219 avr: added device n20 back in. 2025-03-25 00:39:44 +01:00
Martin Preuss
791afb80f8 avr: added macros M_UART_HW_Uart_RxCharHalf/FullDuplexIsr 2025-03-25 00:39:28 +01:00
Martin Preuss
924c4d27e8 avr: added network/msg/crc.asm 2025-03-25 00:38:42 +01:00
Martin Preuss
cac611deae avr: use NETMSG functions, increase waiting times. 2025-03-25 00:38:12 +01:00
Martin Preuss
aee2c384c8 avr: fixed includes. 2025-03-25 00:37:12 +01:00
Martin Preuss
78fda7727a avr: added some comments. 2025-03-24 00:18:50 +01:00
Martin Preuss
45e668ec88 aqhome-tool: flash always 16 bytes at a time 2025-03-24 00:18:28 +01:00
Martin Preuss
c6f1ac94fa increased version number. 2025-03-23 22:41:30 +01:00
Martin Preuss
8c9fd4574d t03: debug; decrease time between stats messages. 2025-03-23 22:41:20 +01:00
Martin Preuss
f9a73a61e9 n14: added debug code. 2025-03-23 22:40:52 +01:00
Martin Preuss
0165b02310 flashing older nodes across t03 now works!
older nodes need the new bootloader which doesn't depend on pagesize because
those older nodes used quite large message sizes which are not supported
across t03 nodes (we would need to much RAM on t03 for this).
2025-03-23 22:40:34 +01:00
Martin Preuss
24dc3e1c0a aqhome: fixed flashing messages and code
use consisten order of arguments.
2025-03-23 22:38:37 +01:00
Martin Preuss
7b6cb4da34 aqhome-tool: decreased verbosity. 2025-03-23 22:37:55 +01:00
Martin Preuss
c8fcd46325 aqhome-data: changed return type. 2025-03-23 22:37:34 +01:00
Martin Preuss
3ffc4a3410 fixed/added valgrind caller scripts. 2025-03-23 16:58:23 +01:00
Martin Preuss
52eb92a00c fixed memory leaks. 2025-03-23 16:58:07 +01:00
Martin Preuss
ebce002614 avr: share code. 2025-03-23 01:08:33 +01:00
Martin Preuss
595f983071 avr/uart_hw, t03: cross messaging now works!! 2025-03-22 23:44:15 +01:00
Martin Preuss
8586269033 avr/t03: more tests. 2025-03-22 13:00:35 +01:00
Martin Preuss
0f598a5552 avr/uart_hw: tty1 works in send and receive direction. 2025-03-22 13:00:20 +01:00
Martin Preuss
236f6832a3 avr: fixed a critical bug (don't decrement used bytes on peek!) 2025-03-22 12:59:35 +01:00
Martin Preuss
373a553ac8 avr/uart_hw: basically works for a while then stops... 2025-03-21 20:55:50 +01:00
Martin Preuss
2964347e7b adjusted to latest changes. 2025-03-21 20:55:11 +01:00
Martin Preuss
3f0e9c9294 increased verbosity. 2025-03-21 20:54:57 +01:00
Martin Preuss
0b946c5748 aqhome-tool: fixed a bug. 2025-03-21 20:54:41 +01:00
Martin Preuss
c808f8640e aqhome-nodes: allow for TTY interface without ATTN line. 2025-03-21 20:54:19 +01:00
Martin Preuss
1fa0d976d2 increased version. 2025-03-19 23:22:59 +01:00
Martin Preuss
091307290e aqhome-react: fixed timeprogram module. 2025-03-19 23:22:46 +01:00
Martin Preuss
7a045abcc2 scripts: use "adddata" instead of "addjsondata". 2025-03-19 23:22:26 +01:00
Martin Preuss
95d589b126 aqhome-react: fixed argument checks. 2025-03-19 23:21:55 +01:00
Martin Preuss
d27664d7c9 aqhome-data: no tagList needed here. 2025-03-19 23:21:31 +01:00
Martin Preuss
ebf9c6eb30 aqhome-tool: fixed return value ("1" stops the calling loop). 2025-03-19 23:21:03 +01:00
Martin Preuss
fef6011426 aqhome-react: show values sent. 2025-03-19 23:20:23 +01:00
Martin Preuss
daa07428eb aqhome apps: decreased verbosity. 2025-03-19 23:19:52 +01:00
Martin Preuss
0d8d684e78 prepared release 0.0.6. 2025-03-18 22:58:39 +01:00
Martin Preuss
bab6721b2c aqhome-react.sh: fixed order of arguments (enables "test" and "unittest"). 2025-03-18 22:58:27 +01:00
Martin Preuss
d468d2fb1a aqhome-tool: exchange CONNECT messages for data IPC. 2025-03-18 22:57:51 +01:00
Martin Preuss
d897f40903 aqhome-react: add missing includes. 2025-03-18 22:56:42 +01:00
Martin Preuss
9a7a7e75f9 aqhome-react: enable unit tests. 2025-03-18 22:56:10 +01:00
Martin Preuss
a14c2c892c libtest: no longer include old files. 2025-03-18 22:55:32 +01:00
Martin Preuss
cc64f793ec build: add missing files. 2025-03-18 22:55:08 +01:00
Martin Preuss
32d5287a3a aqhome-mqttlog: unify arguments. 2025-03-18 22:54:34 +01:00
Martin Preuss
4dd3decb06 aqhome-nodes: fixed a bug (reversed src and dest addresses). 2025-03-18 22:54:11 +01:00
Martin Preuss
171caacc92 aqhome-apps: no longer included removed files. 2025-03-18 22:53:34 +01:00
Martin Preuss
2320ba3a69 aqhome-data: fixed a bug (don't need tagList for "GetValues"). 2025-03-18 22:51:49 +01:00
Martin Preuss
72c8923bfe avr: more work on uart_hw. 2025-03-14 23:29:43 +01:00
Martin Preuss
14c9ac17a1 avr: disable module for n11. 2025-03-14 21:30:51 +01:00
Martin Preuss
7e745c98e6 aqhome, aqhome-apps: cleanup, removed unneeded files. 2025-03-14 21:22:48 +01:00
Martin Preuss
31d8cb10df Merge branch 'mp-2025_02-ipc2_event2'
Pull latest changes as current state into master branch.
2025-03-11 23:55:31 +01:00
700 changed files with 38767 additions and 23360 deletions

6
0BUILD
View File

@@ -2,7 +2,7 @@
<gwbuild>
<project name="aqhome" version="0.0.4" so_current="0" so_age="0" so_revision="4" write_config_h="TRUE">
<project name="aqhome" version="0.0.12" so_current="0" so_age="0" so_revision="12" write_config_h="TRUE">
<setVar name="package">$(project_name)</setVar>
<setVar name="version">
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
@@ -51,6 +51,8 @@
<setVar name="pkgincludedir">$(includedir)/aqhome/$(package)</setVar>
<setVar name="pkgdatadir">$(datadir)/$(package)</setVar>
<setVar name="httpdatadir">/var/www</setVar>
<option id="enable_testcode" type="string">
<default>TRUE</default>
<choices>TRUE FALSE</choices>
@@ -126,6 +128,7 @@
</option>
<checkheaders>
signal.h
sys/stat.h
@@ -149,6 +152,7 @@
<dep id="gwenhywfar" name="gwenhywfar" minversion="5.11.2" required="TRUE" >
<variables>plugindir gwengui-fox16</variables>
</dep>
<dep id="aqcgi" name="aqcgi" minversion="0.0.1" required="TRUE" />
<!-- <dep id="aqdatabase" name="aqdatabase" minversion="1.99.1" required="TRUE" >
<variables>aqdatabase_typemakerdir</variables>
</dep>

View File

@@ -8,6 +8,7 @@
aqhome-data
aqhome-nodes
aqhome-react
aqhome-cgi
</subdirs>
</gwbuild>

145
apps/aqhome-cgi/0BUILD Normal file
View File

@@ -0,0 +1,145 @@
<?xml?>
<gwbuild>
<target type="Program" name="aqhome-cgi" install="$(libdir)/cgi-bin" >
<includes type="c" >
$(gwenhywfar_cflags)
$(aqcgi_cflags)
-I$(topsrcdir)
-I$(topbuilddir)
-I$(topsrcdir)/apps
-I$(topbuilddir)/apps
-I$(builddir)
-I$(srcdir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
</includes>
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
</setVar>
<setVar name="local/typefiles" >
</setVar>
<setVar name="local/built_sources" >
</setVar>
<setVar name="local/built_headers_pub">
</setVar>
<setVar name="local/built_headers_priv" >
</setVar>
<headers dist="true" >
</headers>
<sources>
$(local/typefiles)
main.c
</sources>
<useTargets>
aqhome
aqhomecgi
aqhcgi_service
</useTargets>
<libraries>
$(gwenhywfar_libs)
-lm
$(aqcgi_libs)
</libraries>
<subdirs>
</subdirs>
<extradist>
</extradist>
</target>
<target type="ConvenienceLibrary" name="aqhomecgi" >
<includes type="c" >
$(gwenhywfar_cflags)
-I$(topsrcdir)
-I$(topbuilddir)
-I$(topsrcdir)/apps
-I$(topbuilddir)/apps
-I$(builddir)
-I$(srcdir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
</includes>
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
</setVar>
<setVar name="local/typefiles" >
</setVar>
<setVar name="local/built_sources" >
</setVar>
<setVar name="local/built_headers_pub">
</setVar>
<setVar name="local/built_headers_priv" >
</setVar>
<headers dist="true" >
service_file.h
service_file_p.h
</headers>
<sources>
$(local/typefiles)
service_file.c
</sources>
<useTargets>
aqhome
aqhcgi_service
aqhcgi_modules
</useTargets>
<libraries>
$(gwenhywfar_libs)
-lm
$(aqcgi_libs)
</libraries>
<subdirs>
service
modules
</subdirs>
<extradist>
</extradist>
</target>
</gwbuild>

23
apps/aqhome-cgi/README Normal file
View File

@@ -0,0 +1,23 @@
Modules:
- login
- signup
- main
- devices
- list
- show?name="nodes/12345678"
- add
- edit
- delete
- values
- rooms
- users
- list
- show?alias="admin"
- add
- edit
- delete
- dashboards

0
apps/aqhome-cgi/dummy.c Normal file
View File

181
apps/aqhome-cgi/main.c Normal file
View File

@@ -0,0 +1,181 @@
#include "./service_file.h"
#include "aqhome-cgi/modules/mroot.h"
#include "aqhome/aqhome.h"
#include <aqcgi/cgi.h>
#include <aqcgi/request.h>
#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/nogui.h>
#include <gwenhywfar/logger.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#define AQHOME_CGI_LOGFILE "/var/www/aqhome-cgi/log/aqhome-cgi.log"
#define AQHOME_CGI_DEFAULT_STATIC_FILES "0-build/services/static"
#define AQHOME_CGI_DEFAULT_RUNTIME_FILES "0-build/services/runtime"
void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles);
int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles);
AQH_MODULE *_loadModule(AQH_SERVICE *sv, AQCGI_REQUEST *rq, AQH_MODULE *mParent, const char *sModuleName);
static void logStart(void);
int main(int argc, char **argv)
{
GWEN_GUI *gui;
AQCGI_REQUEST *rq;
GWEN_Init();
gui=GWEN_NoGui_new();
GWEN_Gui_SetGui(gui);
logStart();
GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_Open(AQH_LOGDOMAIN, "aqhome", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_Open(AQCGI_LOGDOMAIN, "aqcgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_Open(NULL, "aqhome-cgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
DBG_ERROR(NULL, "Init CGI");
AQCGI_Init();
GWEN_Logger_Close(GWEN_LOGDOMAIN);
GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
rq=AQCGI_ReadRequest();
if (rq) {
const char *sPathStaticFiles;
const char *sPathRuntimeFiles;
sPathStaticFiles=getenv("AQHOME_STATIC_FILES");
if (!(sPathStaticFiles && *sPathStaticFiles))
sPathStaticFiles=AQHOME_CGI_DEFAULT_STATIC_FILES;
sPathRuntimeFiles=getenv("AQHOME_RUNTIME_FILES");
if (!(sPathRuntimeFiles && *sPathRuntimeFiles))
sPathRuntimeFiles=AQHOME_CGI_DEFAULT_RUNTIME_FILES;
_handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles);
}
else {
fprintf(stdout, "Content-type: text/plain\n\n");
fprintf(stdout, "Error: No Request!\n");
return 0;
}
AQCGI_Fini();
return 0;
}
void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles)
{
AQH_SERVICE *sv;
int rv;
sv=AQH_ServiceFiles_new(sPathRuntimeFiles);
rv=_handlePath(sv, rq, sPathStaticFiles);
if (rv<0) {
}
AQH_Service_free(sv);
}
int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles)
{
AQH_MODULE *mRoot;
AQH_MODULE *mParent;
const GWEN_STRINGLIST *sl;
mRoot=AQH_ModRoot_new(sv, sPathStaticFiles);
mParent=mRoot;
sl=AQCGI_Request_GetStringlistPath(rq);
if (sl) {
GWEN_STRINGLISTENTRY *se;
se=GWEN_StringList_FirstEntry(sl);
while(se) {
GWEN_STRINGLISTENTRY *seNext;
const char *s;
seNext=GWEN_StringListEntry_Next(se);
s=GWEN_StringListEntry_Data(se);
if (s && *s) {
if (seNext) {
AQH_MODULE *m;
DBG_ERROR(NULL, "Entry: %s (%s)", s, seNext?"not last":"last");
m=AQH_ModService_LoadSubModule(mParent, rq, s);
if (m==NULL) {
AQH_Module_free(mRoot);
AQCGI_SendResponseWithStatus(rq, 404, "Not found");
return GWEN_ERROR_GENERIC;
}
mParent=m;
}
else {
int rv;
/* last, let module handle remaining part */
rv=AQH_ModService_HandleRequest(mParent, rq, s);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
AQH_Module_free(mRoot);
return rv;
}
break;
}
}
se=seNext;
}
AQH_Module_free(mRoot);
return 0;
}
else {
AQH_Module_free(mRoot);
return GWEN_ERROR_GENERIC;
}
}
void logStart()
{
FILE *f;
f=fopen(AQHOME_CGI_LOGFILE, "a+");
if (f!=NULL) {
fprintf(f, "Started.\n");
fclose(f);
}
}

View File

@@ -2,19 +2,21 @@
<gwbuild>
<target type="ConvenienceLibrary" name="aqhevents" >
<target type="ConvenienceLibrary" name="aqhcgi_modules" >
<includes type="c" >
$(gwenhywfar_cflags)
$(aqdatabase_cflags)
-I$(topsrcdir)
-I$(topbuilddir)
-I$(topsrcdir)/apps
-I$(topbuilddir)/apps
-I$(builddir)
-I$(srcdir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
--include=$(aqdatabase_AQDATABASE_TYPEMAKERDIR)/c
</includes>
@@ -23,7 +25,7 @@
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
<setVar name="tm2flags-INACTIVE" >
--api=AQHOME_API
</setVar>
@@ -41,31 +43,28 @@
</setVar>
<headers dist="false" install="$(pkgincludedir)/data" >
<headers dist="false" install="$(pkgincludedir)/service" >
$(local/built_headers_pub)
</headers>
<headers dist="true" install="$(pkgincludedir)/data" >
eventsubscription.h
eventtimer.h
eventhandler.h
<headers dist="true" install="$(pkgincludedir)/service" >
mservice.h
mroot.h
</headers>
<headers dist="true" >
eventsubscription_p.h
eventtimer_p.h
eventhandler_p.h
mservice_p.h
mroot_p.h
</headers>
<sources>
$(local/typefiles)
eventsubscription.c
eventtimer.c
eventhandler.c
mservice.c
mroot.c
</sources>
@@ -77,11 +76,9 @@
</useTargets>
<subdirs>
static
</subdirs>
</target>
</gwbuild>

View File

@@ -0,0 +1,246 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./mroot_p.h"
#include "aqhome-cgi/service/module.h"
#include <gwenhywfar/debug.h>
#include <gwenhywfar/timestamp.h>
/* ------------------------------------------------------------------------------------------------
* defs and enums
* ------------------------------------------------------------------------------------------------
*/
/* ------------------------------------------------------------------------------------------------
* global vars
* ------------------------------------------------------------------------------------------------
*/
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
static int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq);
static int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq);
static AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq);
/* ------------------------------------------------------------------------------------------------
* code
* ------------------------------------------------------------------------------------------------
*/
AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder)
{
AQH_MODULE *m;
m=AQH_ModService_new(sv, baseFolder);
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
return m;
}
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName)
{
return NULL;
}
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
{
if (strcasecmp(sLastPathElem, "login")==0)
return _handleRqLogin(m, rq);
else if (strcasecmp(sLastPathElem, "signup")==0) {
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
return GWEN_ERROR_NOT_IMPLEMENTED;
}
else if (strcasecmp(sLastPathElem, "confirm")==0) {
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
return GWEN_ERROR_NOT_IMPLEMENTED;
}
else {
AQCGI_SendResponseWithStatus(rq, 404, "Not Found");
return GWEN_ERROR_NOT_IMPLEMENTED;
}
}
int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq)
{
int rv;
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET)
rv=AQH_ModService_RespondWithFile(m, rq, "en", "login.html");
else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST)
rv=_handleRqLoginPost(m, rq);
else {
DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq));
AQCGI_SendResponseWithStatus(rq, 405, "Method No Allowed");
return GWEN_ERROR_INVALID;
}
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
return 0;
}
int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq)
{
AQH_SERVICE *sv;
AQH_USER *user;
AQH_SESSION *session;
GWEN_BUFFER *dbuf;
GWEN_TIMESTAMP *ts;
int rv;
DBG_ERROR(NULL, "Handling request");
sv=AQH_ModService_GetService(m);
user=_getAndCheckUser(m, rq);
if (user==NULL) {
DBG_INFO(NULL, "here");
return GWEN_ERROR_GENERIC;
}
ts=GWEN_Timestamp_NowInLocalTime();
AQH_User_SetTimestampLastLogin(user, ts);
DBG_ERROR(NULL, "Saving user");
rv=AQH_Service_SaveUser(sv, user);
if (rv<0) {
DBG_ERROR(NULL, "Error saving user \"%s\"", AQH_User_GetAlias(user));
AQCGI_SendResponseWithStatus(rq, 500, "Internal Error");
AQH_User_free(user);
return rv;
}
/* generate session */
DBG_ERROR(NULL, "Generating session");
dbuf=GWEN_Buffer_new(0, 64, 0, 1);
AQCGI_GenerateSessionId(dbuf);
session=AQH_Session_new();
AQH_Session_SetTimestampCreation(session, ts);
AQH_Session_SetTimestampLastAccess(session, ts);
AQH_Session_SetUid(session, GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_free(dbuf);
AQH_Session_SetUserAlias(session, AQH_User_GetAlias(user));
rv=AQH_Service_AddSession(sv, session);
if (rv<0) {
DBG_ERROR(NULL, "Error adding session for user \"%s\"", AQH_User_GetAlias(user));
AQCGI_SendResponseWithStatus(rq, 500, "Internal Error");
AQH_Session_free(session);
AQH_User_free(user);
return GWEN_ERROR_INTERNAL;
}
/* add Set-Cookie header */
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendArgs(dbuf, "Set-Cookie: session=%s; max-age=3600", AQH_Session_GetUid(session));
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(dbuf));
/* finish */
AQCGI_SendResponseWithStatus(rq, 200, "Ok");
AQH_Session_free(session);
AQH_User_free(user);
return 0;
}
AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
{
GWEN_DB_NODE *dbPost;
dbPost=AQCGI_Request_GetDbPostBody(rq);
if (dbPost) {
AQH_SERVICE *sv;
const char *sUserName;
const char *sPasswd;
AQH_USER *user;
const char *hashedPaswd;
GWEN_BUFFER *buf;
sv=AQH_ModService_GetService(m);
sUserName=GWEN_DB_GetCharValue(dbPost, "userid", 0, NULL);
sPasswd=GWEN_DB_GetCharValue(dbPost, "password", 0, NULL);
if (!(sUserName && *sUserName && sPasswd && *sPasswd)) {
DBG_ERROR(NULL, "Either user name or password missing");
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
return NULL;
}
DBG_ERROR(NULL, "Loading user \"%s\" (%p)", sUserName, sv);
user=AQH_Service_LoadUser(sv, sUserName);
if (user==NULL) {
DBG_ERROR(NULL, "User \"%s\" not found", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
return NULL;
}
DBG_ERROR(NULL, "Loaded user \"%s\"", sUserName);
if (AQH_User_GetState(user)!=AQH_UserState_Active) {
DBG_ERROR(NULL, "User \"%s\" not active", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
AQH_User_free(user);
return NULL;
}
hashedPaswd=AQH_User_GetHashedPassword(user);
if (!(hashedPaswd && *hashedPaswd)) {
DBG_ERROR(NULL, "User \"%s\" has no hashed password", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
AQH_User_free(user);
return NULL;
}
buf=GWEN_Buffer_new(0, 256, 0, 1);
AQCGI_HashMd256ToBuffer(sPasswd, buf);
DBG_ERROR(NULL, "Hashed password: [%s]", GWEN_Buffer_GetStart(buf));
if (strcasecmp(GWEN_Buffer_GetStart(buf), hashedPaswd)!=0) {
DBG_ERROR(NULL, "Bad password for user \"%s\"", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
GWEN_Buffer_free(buf);
AQH_User_free(user);
return NULL;
}
GWEN_Buffer_free(buf);
DBG_ERROR(NULL, "User \"%s\" accepted", sUserName);
return user;
}
else {
DBG_ERROR(NULL, "No POST data");
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
return NULL;
}
}

View File

@@ -0,0 +1,27 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_CGI_MROOT_H
#define AQHOME_CGI_MROOT_H
#include <aqhome-cgi/modules/mservice.h>
#include <aqcgi/request.h>
#include <gwenhywfar/buffer.h>
AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder);
AQH_MODULE *AQH_ModRoot_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
int AQH_ModRoot_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
#endif

View File

@@ -1,16 +1,18 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#ifndef AQHOME_CGI_MROOT_P_H
#define AQHOME_CGI_MROOT_P_H
#include "aqhome-cgi/modules/mroot.h"
#endif
#include <aqhome/ipc/nodes/ipc_nodes.h>

View File

@@ -0,0 +1,291 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./mservice_p.h"
#include "aqhome-cgi/service/module.h"
#include <gwenhywfar/debug.h>
/* ------------------------------------------------------------------------------------------------
* defs and enums
* ------------------------------------------------------------------------------------------------
*/
#define AQH_MOD_SERVICE_HEADERFILE "header.html"
#define AQH_MOD_SERVICE_FOOTERFILE "footer.html"
/* ------------------------------------------------------------------------------------------------
* global vars
* ------------------------------------------------------------------------------------------------
*/
GWEN_INHERIT(AQH_MODULE, AQH_MOD_SERVICE)
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
/* ------------------------------------------------------------------------------------------------
* code
* ------------------------------------------------------------------------------------------------
*/
AQH_MODULE *AQH_ModService_new(AQH_SERVICE *sv, const char *baseFolder)
{
AQH_MODULE *m;
AQH_MOD_SERVICE *xm;
m=AQH_Module_new();
GWEN_NEW_OBJECT(AQH_MOD_SERVICE, xm);
GWEN_INHERIT_SETDATA(AQH_MODULE, AQH_MOD_SERVICE, m, xm, _freeData);
xm->service=sv;
xm->baseFolder=(baseFolder && *baseFolder)?strdup(baseFolder):NULL;
return m;
}
void _freeData(GWEN_UNUSED void *bp, void *p)
{
AQH_MOD_SERVICE *xm;
xm=(AQH_MOD_SERVICE*) p;
free(xm->baseFolder);
GWEN_FREE_OBJECT(xm);
}
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
return xm->service;
}
}
return NULL;
}
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
return xm->baseFolder;
}
}
return NULL;
}
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
xm->handleRequestFn=fn;
}
}
}
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
xm->loadSubModuleFn=fn;
}
}
}
int AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
{
if (m && dbuf) {
AQH_MODULE *mParent;
mParent=AQH_Module_Tree2_GetParent(m);
if (mParent) {
int rv;
rv=AQH_ModService_AddHeader(mParent, lang, dbuf);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
}
return AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_HEADERFILE, dbuf);
}
DBG_ERROR(NULL, "Argument missing");
return GWEN_ERROR_INVALID;
}
int AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
{
if (m && dbuf) {
AQH_MODULE *mParent;
int rv;
rv=AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_FOOTERFILE, dbuf);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
mParent=AQH_Module_Tree2_GetParent(m);
if (mParent) {
int rv;
rv=AQH_ModService_AddFooter(mParent, lang, dbuf);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
}
return 0;
}
else {
DBG_ERROR(NULL, "Argument missing");
return GWEN_ERROR_INVALID;
}
}
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename)
{
GWEN_BUFFER *buf;
int rv;
buf=GWEN_Buffer_new(0, 256, 0, 1);
rv=AQH_ModService_AddHeader(m, lang, buf);
if (rv<0) {
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
GWEN_Buffer_free(buf);
return GWEN_ERROR_INTERNAL;
}
rv=AQH_ModService_ReadStaticFile(m, lang, sFilename, buf);
if (rv<0) {
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
GWEN_Buffer_free(buf);
return GWEN_ERROR_INTERNAL;
}
rv=AQH_ModService_AddFooter(m, lang, buf);
if (rv<0) {
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
GWEN_Buffer_free(buf);
return GWEN_ERROR_INTERNAL;
}
AQCGI_Request_SetBufferResponseBody(rq, buf);
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
AQCGI_SendResponseWithStatus(rq, 200, "Ok");
return 0;
}
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm && xm->handleRequestFn)
return xm->handleRequestFn(m, rq, sLastPathElem);
}
return GWEN_ERROR_NOT_IMPLEMENTED;
}
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm && xm->loadSubModuleFn)
return xm->loadSubModuleFn(m, rq, sModuleName);
}
return NULL;
}
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf)
{
if (m && filename && dbuf) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
GWEN_BUFFER *fbuf;
int rv;
fbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendString(fbuf, xm->baseFolder);
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
GWEN_Buffer_AppendString(fbuf, (lang && *lang)?lang:"en");
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
GWEN_Buffer_AppendString(fbuf, filename);
DBG_ERROR(NULL, "Reading file \"%s\"", GWEN_Buffer_GetStart(fbuf));
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), dbuf);
if (rv<0) {
DBG_ERROR(NULL, "Read(%s): %d", GWEN_Buffer_GetStart(fbuf), rv);
GWEN_Buffer_free(fbuf);
return rv;
}
GWEN_Buffer_free(fbuf);
return 0;
}
}
DBG_ERROR(NULL, "Any arg is missing (or is not a AQH_MOD_SERVICE object)");
return GWEN_ERROR_INTERNAL;
}

View File

@@ -0,0 +1,46 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_CGI_MSERVICE_H
#define AQHOME_CGI_MSERVICE_H
#include <aqhome-cgi/service/module.h>
#include <aqhome-cgi/service/service.h>
#include <aqcgi/request.h>
#include <gwenhywfar/buffer.h>
typedef int (*AQH_MODSERVICE_HANDLEREQUEST_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
typedef AQH_MODULE* (*AQH_MODSERVICE_LOADSUBMODULE_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
AQH_MODULE *AQH_ModService_new(AQH_SERVICE *sv, const char *baseFolder);
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m);
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m);
int AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
int AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename);
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf);
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn);
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn);
#endif

View File

@@ -0,0 +1,27 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_CGI_MSERVICE_P_H
#define AQHOME_CGI_MSERVICE_P_H
#include "aqhome-cgi/modules/mservice.h"
typedef struct AQH_MOD_SERVICE AQH_MOD_SERVICE;
struct AQH_MOD_SERVICE {
AQH_SERVICE *service;
char *baseFolder;
AQH_MODSERVICE_HANDLEREQUEST_FN handleRequestFn;
AQH_MODSERVICE_LOADSUBMODULE_FN loadSubModuleFn;
};
#endif

View File

@@ -0,0 +1,7 @@
<?xml?>
<gwbuild>
<subdirs>
en
</subdirs>
</gwbuild>

View File

@@ -0,0 +1,13 @@
<?xml?>
<gwbuild>
<data dist="true" install="$(httpdatadir)/aqhome-cgi/static/en">
header.html
footer.html
login.html
</data>
</gwbuild>

View File

@@ -0,0 +1,4 @@
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<!-- copyright (c) 2025 by martin@libchipcard.de -->
<meta name="generator" content="FTE 1.1" />
<meta name="revised" content="martin,2025-06-12" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta name="author" content="martin" />
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<title>AqHome</title>
</head>
<body>

View File

@@ -0,0 +1,25 @@
<div class="main">
<h1>AqHome</h1>
<h3>Enter your login credentials</h3>
<form action="login" method="post">
<label for="userid">Username:</label>
<input type="text" id="userid" name="userid" placeholder="Enter your Username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" placeholder="Enter your Password" required>
<div class="wrap">
<button type="submit">Submit</button>
</div>
</form>
<p>Not registered?
<a href="signup" style="text-decoration: none;">
Create an account
</a>
</p>
</div>
</body>
</html>

View File

@@ -2,12 +2,16 @@
<gwbuild>
<target type="ConvenienceLibrary" name="aqhservice" >
<target type="ConvenienceLibrary" name="aqhcgi_service" >
<includes type="c" >
$(gwenhywfar_cflags)
-I$(topsrcdir)
-I$(topbuilddir)
-I$(topsrcdir)/apps
-I$(topbuilddir)/apps
-I$(builddir)
-I$(srcdir)
</includes>
<includes type="tm2" >
@@ -21,7 +25,7 @@
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
<setVar name="tm2flags-INACTIVE" >
--api=AQHOME_API
</setVar>

View File

@@ -0,0 +1,20 @@
- service:
- userList
- rootModule
- sessionList
- user:
- modulePerms
- module:
- roleList
- permDefList
- session

View File

@@ -15,6 +15,7 @@
with_db
with_list1
with_list2
with_tree2
nodup
nocopy
</flags>
@@ -22,8 +23,8 @@
<headers>
<header type="sys" loc="pre">aqhome/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="post">aqhome/service/role.h</header>
<header type="sys" loc="post">aqhome/service/permdef.h</header>
<header type="sys" loc="post">aqhome-cgi/service/role.h</header>
<header type="sys" loc="post">aqhome-cgi/service/permdef.h</header>
</headers>
<inlines>
@@ -31,6 +32,13 @@
</lang>
<defines>
<define id="AQH_MODULE_FLAGS" prefix="AQH_MODULE_FLAGS_">
<item name="ACTIVE" value="0x00000001" />
</define>
</defines>
<members>
@@ -41,6 +49,13 @@
<flags>with_getbymember</flags>
</member>
<member name="flags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags</flags>
</member>
<member name="name" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>

View File

@@ -20,7 +20,7 @@
<headers>
<header type="sys" loc="pre">aqhome/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="post">aqhome/service/role.h</header>
<header type="sys" loc="post">aqhome-cgi/service/role.h</header>
</headers>
<inlines>

View File

@@ -0,0 +1,355 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
//#define DISABLE_DEBUGLOG
#include "aqhome-cgi/service/service_p.h"
#include <gwenhywfar/stringlist.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
GWEN_INHERIT_FUNCTIONS(AQH_SERVICE);
GWEN_LIST_FUNCTIONS(AQH_SERVICE, AQH_Service);
AQH_SERVICE *AQH_Service_new(void)
{
AQH_SERVICE *sv;
GWEN_NEW_OBJECT(AQH_SERVICE, sv);
GWEN_INHERIT_INIT(AQH_SERVICE, sv);
GWEN_LIST_INIT(AQH_SERVICE, sv);
return sv;
}
void AQH_Service_free(AQH_SERVICE *sv)
{
if (sv) {
GWEN_LIST_FINI(AQH_SERVICE, sv);
GWEN_INHERIT_FINI(AQH_SERVICE, sv);
GWEN_FREE_OBJECT(sv);
}
}
#if 0
AQH_MODULE *AQH_Service_GetModuleByPath(const AQH_SERVICE *sv, const char *s)
{
if (sv && s && *s) {
GWEN_STRINGLIST *sl;
sl=GWEN_StringList_fromString2(s, "/", 0,
GWEN_TEXT_FLAGS_DEL_QUOTES |
GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS |
GWEN_TEXT_FLAGS_DEL_MULTIPLE_BLANKS |
GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS);
if (sl) {
GWEN_STRINGLISTENTRY *se;
AQH_MODULE *m;
m=sv->rootModule;
se=GWEN_StringList_FirstEntry(sl);
while(se && m) {
const char *sWantedName;
sWantedName=GWEN_StringListEntry_Data(se);
if (sWantedName && *sWantedName) {
AQH_MODULE *mTemp;
mTemp=AQH_Module_Tree2_GetFirstChild(m);
while(mTemp) {
const char *sModName;
sModName=AQH_Module_GetName(mTemp);
if (sModName && *sModName && 0==strcasecmp(sModName, sWantedName))
break;
mTemp=AQH_Module_Tree2_GetNext(mTemp);
}
if (mTemp==NULL) {
DBG_ERROR(NULL, "Module \%s\" not found", sWantedName);
GWEN_StringList_free(sl);
return NULL;
}
m=mTemp;
}
else {
DBG_ERROR(NULL, "Empty path element in \"%s\"", s);
GWEN_StringList_free(sl);
return NULL;
}
se=GWEN_StringListEntry_Next(se);
} /* while(se && m) */
GWEN_StringList_free(sl);
return m;
}
else {
DBG_ERROR(NULL, "Bad path \"%s\"", s);
}
}
return NULL;
}
#endif
int AQH_Service_HandleRequest(AQH_SERVICE *sv, AQCGI_REQUEST *req)
{
return (sv && sv->handleRequestFn)?(sv->handleRequestFn(sv, req)):GWEN_ERROR_NOT_IMPLEMENTED;
}
AQH_USER *AQH_Service_LoadUser(AQH_SERVICE *sv, const char *s)
{
return (sv && sv->loadUserFn)?(sv->loadUserFn(sv, s)):NULL;
}
int AQH_Service_SaveUser(AQH_SERVICE *sv, AQH_USER *user)
{
return (sv && sv->saveUserFn)?(sv->saveUserFn(sv, user)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQH_Service_AddUser(AQH_SERVICE *sv, AQH_USER *user)
{
return (sv && sv->addUserFn)?(sv->addUserFn(sv, user)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQH_Service_DelUser(AQH_SERVICE *sv, const char *s)
{
return (sv && sv->delUserFn)?(sv->delUserFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
}
GWEN_STRINGLIST *AQH_Service_ListUsers(AQH_SERVICE *sv)
{
return (sv && sv->listUsersFn)?(sv->listUsersFn(sv)):NULL;
}
AQH_MODULE *AQH_Service_LoadModule(AQH_SERVICE *sv, const char *s)
{
return (sv && sv->loadModuleFn)?(sv->loadModuleFn(sv, s)):NULL;
}
int AQH_Service_SaveModule(AQH_SERVICE *sv, AQH_MODULE *module)
{
return (sv && sv->saveModuleFn)?(sv->saveModuleFn(sv, module)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQH_Service_AddModule(AQH_SERVICE *sv, AQH_MODULE *module)
{
return (sv && sv->addModuleFn)?(sv->addModuleFn(sv, module)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQH_Service_DelModule(AQH_SERVICE *sv, const char *s)
{
return (sv && sv->delModuleFn)?(sv->delModuleFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
}
GWEN_STRINGLIST *AQH_Service_ListModules(AQH_SERVICE *sv)
{
return (sv && sv->listModulesFn)?(sv->listModulesFn(sv)):NULL;
}
AQH_SESSION* AQH_Service_LoadSession(AQH_SERVICE *sv, const char *s)
{
return (sv && sv->loadSessionFn)?(sv->loadSessionFn(sv, s)):NULL;
}
int AQH_Service_SaveSession(AQH_SERVICE *sv, AQH_SESSION *session)
{
return (sv && sv->saveSessionFn)?(sv->saveSessionFn(sv, session)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQH_Service_AddSession(AQH_SERVICE *sv, AQH_SESSION *session)
{
return (sv && sv->addSessionFn)?(sv->addSessionFn(sv, session)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQH_Service_DelSession(AQH_SERVICE *sv, const char *s)
{
return (sv && sv->delSessionFn)?(sv->delSessionFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
}
void AQH_Service_SetHandleRequestFn(AQH_SERVICE *sv, AQH_SERVICE_HANDLEREQUEST_FN f)
{
if (sv)
sv->handleRequestFn=f;
}
void AQH_Service_SetLoadUserFn(AQH_SERVICE *sv, AQH_SERVICE_LOADUSER_FN f)
{
if (sv)
sv->loadUserFn=f;
}
void AQH_Service_SetSaveUserFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEUSER_FN f)
{
if (sv)
sv->saveUserFn=f;
}
void AQH_Service_SetAddUserFn(AQH_SERVICE *sv, AQH_SERVICE_ADDUSER_FN f)
{
if (sv)
sv->addUserFn=f;
}
void AQH_Service_SetDelUserFn(AQH_SERVICE *sv, AQH_SERVICE_DELUSER_FN f)
{
if (sv)
sv->delUserFn=f;
}
void AQH_Service_SetListUsersFn(AQH_SERVICE *sv, AQH_SERVICE_LISTUSERS_FN f)
{
if (sv)
sv->listUsersFn=f;
}
void AQH_Service_SetLoadModuleFn(AQH_SERVICE *sv, AQH_SERVICE_LOADMODULE_FN f)
{
if (sv)
sv->loadModuleFn=f;
}
void AQH_Service_SetSaveModuleFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEMODULE_FN f)
{
if (sv)
sv->saveModuleFn=f;
}
void AQH_Service_SetAddModuleFn(AQH_SERVICE *sv, AQH_SERVICE_ADDMODULE_FN f)
{
if (sv)
sv->addModuleFn=f;
}
void AQH_Service_SetDelModuleFn(AQH_SERVICE *sv, AQH_SERVICE_DELMODULE_FN f)
{
if (sv)
sv->delModuleFn=f;
}
void AQH_Service_SetListModulesFn(AQH_SERVICE *sv, AQH_SERVICE_LISTMODULES_FN f)
{
if (sv)
sv->listModulesFn=f;
}
void AQH_Service_SetLoadSessionFn(AQH_SERVICE *sv, AQH_SERVICE_LOADSESSION_FN f)
{
if (sv)
sv->loadSessionFn=f;
}
void AQH_Service_SetSaveSessionFn(AQH_SERVICE *sv, AQH_SERVICE_SAVESESSION_FN f)
{
if (sv)
sv->saveSessionFn=f;
}
void AQH_Service_SetAddSessionFn(AQH_SERVICE *sv, AQH_SERVICE_ADDSESSION_FN f)
{
if (sv)
sv->addSessionFn=f;
}
void AQH_Service_SetDelSessionFn(AQH_SERVICE *sv, AQH_SERVICE_DELSESSION_FN f)
{
if (sv)
sv->delSessionFn=f;
}
void AQH_Service_SetListSessionsFn(AQH_SERVICE *sv, AQH_SERVICE_LISTSESSIONS_FN f)
{
if (sv)
sv->listSessionsFn=f;
}

View File

@@ -0,0 +1,104 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_SERVICE_H
#define AQHOME_SERVICE_H
#include <aqhome/api.h>
#include <gwenhywfar/inherit.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/stringlist.h>
typedef struct AQH_SERVICE AQH_SERVICE;
GWEN_INHERIT_FUNCTION_DEFS(AQH_SERVICE);
GWEN_LIST_FUNCTION_DEFS(AQH_SERVICE, AQH_Service);
#include "aqhome-cgi/service/user.h"
#include "aqhome-cgi/service/module.h"
#include "aqhome-cgi/service/session.h"
#include <aqcgi/cgi.h>
typedef int (*AQH_SERVICE_HANDLEREQUEST_FN)(AQH_SERVICE *sv, AQCGI_REQUEST *req);
typedef AQH_USER* (*AQH_SERVICE_LOADUSER_FN)(AQH_SERVICE *sv, const char *s);
typedef int (*AQH_SERVICE_SAVEUSER_FN)(AQH_SERVICE *sv, AQH_USER *user);
typedef int (*AQH_SERVICE_ADDUSER_FN)(AQH_SERVICE *sv, AQH_USER *user);
typedef int (*AQH_SERVICE_DELUSER_FN)(AQH_SERVICE *sv, const char *s);
typedef GWEN_STRINGLIST* (*AQH_SERVICE_LISTUSERS_FN)(AQH_SERVICE *sv);
typedef AQH_MODULE* (*AQH_SERVICE_LOADMODULE_FN)(AQH_SERVICE *sv, const char *s);
typedef int (*AQH_SERVICE_SAVEMODULE_FN)(AQH_SERVICE *sv, AQH_MODULE *module);
typedef int (*AQH_SERVICE_ADDMODULE_FN)(AQH_SERVICE *sv, AQH_MODULE *module);
typedef int (*AQH_SERVICE_DELMODULE_FN)(AQH_SERVICE *sv, const char *s);
typedef GWEN_STRINGLIST* (*AQH_SERVICE_LISTMODULES_FN)(AQH_SERVICE *sv);
typedef AQH_SESSION* (*AQH_SERVICE_LOADSESSION_FN)(AQH_SERVICE *sv, const char *s);
typedef int (*AQH_SERVICE_SAVESESSION_FN)(AQH_SERVICE *sv, AQH_SESSION *session);
typedef int (*AQH_SERVICE_ADDSESSION_FN)(AQH_SERVICE *sv, AQH_SESSION *session);
typedef int (*AQH_SERVICE_DELSESSION_FN)(AQH_SERVICE *sv, const char *s);
typedef GWEN_STRINGLIST* (*AQH_SERVICE_LISTSESSIONS_FN)(AQH_SERVICE *sv);
AQH_SERVICE *AQH_Service_new(void);
void AQH_Service_free(AQH_SERVICE *sv);
int AQH_Service_HandleRequest(AQH_SERVICE *sv, AQCGI_REQUEST *req);
AQH_USER *AQH_Service_LoadUser(AQH_SERVICE *sv, const char *s);
int AQH_Service_SaveUser(AQH_SERVICE *sv, AQH_USER *user);
int AQH_Service_AddUser(AQH_SERVICE *sv, AQH_USER *user);
int AQH_Service_DelUser(AQH_SERVICE *sv, const char *s);
GWEN_STRINGLIST *AQH_Service_ListUsers(AQH_SERVICE *sv);
AQH_MODULE *AQH_Service_LoadModule(AQH_SERVICE *sv, const char *s);
int AQH_Service_SaveModule(AQH_SERVICE *sv, AQH_MODULE *module);
int AQH_Service_AddModule(AQH_SERVICE *sv, AQH_MODULE *module);
int AQH_Service_DelModule(AQH_SERVICE *sv, const char *s);
GWEN_STRINGLIST *AQH_Service_ListModules(AQH_SERVICE *sv);
AQH_SESSION* AQH_Service_LoadSession(AQH_SERVICE *sv, const char *s);
int AQH_Service_SaveSession(AQH_SERVICE *sv, AQH_SESSION *session);
int AQH_Service_AddSession(AQH_SERVICE *sv, AQH_SESSION *session);
int AQH_Service_DelSession(AQH_SERVICE *sv, const char *s);
GWEN_STRINGLIST *AQH_Service_ListSessions(AQH_SERVICE *sv);
void AQH_Service_SetHandleRequestFn(AQH_SERVICE *sv, AQH_SERVICE_HANDLEREQUEST_FN f);
void AQH_Service_SetLoadUserFn(AQH_SERVICE *sv, AQH_SERVICE_LOADUSER_FN f);
void AQH_Service_SetSaveUserFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEUSER_FN f);
void AQH_Service_SetAddUserFn(AQH_SERVICE *sv, AQH_SERVICE_ADDUSER_FN f);
void AQH_Service_SetDelUserFn(AQH_SERVICE *sv, AQH_SERVICE_DELUSER_FN f);
void AQH_Service_SetListUsersFn(AQH_SERVICE *sv, AQH_SERVICE_LISTUSERS_FN f);
void AQH_Service_SetLoadModuleFn(AQH_SERVICE *sv, AQH_SERVICE_LOADMODULE_FN f);
void AQH_Service_SetSaveModuleFn(AQH_SERVICE *sv, AQH_SERVICE_SAVEMODULE_FN f);
void AQH_Service_SetAddModuleFn(AQH_SERVICE *sv, AQH_SERVICE_ADDMODULE_FN f);
void AQH_Service_SetDelModuleFn(AQH_SERVICE *sv, AQH_SERVICE_DELMODULE_FN f);
void AQH_Service_SetListModulesFn(AQH_SERVICE *sv, AQH_SERVICE_LISTMODULES_FN f);
void AQH_Service_SetLoadSessionFn(AQH_SERVICE *sv, AQH_SERVICE_LOADSESSION_FN f);
void AQH_Service_SetSaveSessionFn(AQH_SERVICE *sv, AQH_SERVICE_SAVESESSION_FN f);
void AQH_Service_SetAddSessionFn(AQH_SERVICE *sv, AQH_SERVICE_ADDSESSION_FN f);
void AQH_Service_SetDelSessionFn(AQH_SERVICE *sv, AQH_SERVICE_DELSESSION_FN f);
void AQH_Service_SetListSessionsFn(AQH_SERVICE *sv, AQH_SERVICE_LISTSESSIONS_FN f);
#endif

View File

@@ -0,0 +1,45 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_SERVICE_P_H
#define AQHOME_SERVICE_P_H
#include "aqhome-cgi/service/service.h"
struct AQH_SERVICE {
GWEN_INHERIT_ELEMENT(AQH_SERVICE);
GWEN_LIST_ELEMENT(AQH_SERVICE);
AQH_SERVICE_HANDLEREQUEST_FN handleRequestFn;
AQH_SERVICE_LOADUSER_FN loadUserFn;
AQH_SERVICE_SAVEUSER_FN saveUserFn;
AQH_SERVICE_ADDUSER_FN addUserFn;
AQH_SERVICE_DELUSER_FN delUserFn;
AQH_SERVICE_LISTUSERS_FN listUsersFn;
AQH_SERVICE_LOADMODULE_FN loadModuleFn;
AQH_SERVICE_SAVEMODULE_FN saveModuleFn;
AQH_SERVICE_ADDMODULE_FN addModuleFn;
AQH_SERVICE_DELMODULE_FN delModuleFn;
AQH_SERVICE_LISTMODULES_FN listModulesFn;
AQH_SERVICE_LOADSESSION_FN loadSessionFn;
AQH_SERVICE_SAVESESSION_FN saveSessionFn;
AQH_SERVICE_ADDSESSION_FN addSessionFn;
AQH_SERVICE_DELSESSION_FN delSessionFn;
AQH_SERVICE_LISTSESSIONS_FN listSessionsFn;
};
#endif

View File

@@ -22,7 +22,7 @@
<header type="sys" loc="pre">aqhome/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="pre">gwenhywfar/timestamp.h</header>
<header type="sys" loc="post">aqhome/service/user.h</header>
<header type="sys" loc="post">aqhome-cgi/service/user.h</header>
</headers>
<inlines>

View File

@@ -23,7 +23,7 @@
<header type="sys" loc="pre">aqhome/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="pre">gwenhywfar/timestamp.h</header>
<header type="sys" loc="post">aqhome/service/moduleperms.h</header>
<header type="sys" loc="post">aqhome-cgi/service/moduleperms.h</header>
</headers>
<inlines>
@@ -54,6 +54,10 @@
<descr>Waiting for approval by admin</descr>
</item>
<item name="active">
<descr>User active</descr>
</item>
</enum>
</enums>

View File

@@ -0,0 +1,611 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
//#define DISABLE_DEBUGLOG
#include "./service_file_p.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/debug.h>
/* ------------------------------------------------------------------------------------------------
* defs and enums
* ------------------------------------------------------------------------------------------------
*/
#define AQH_SERVICE_FILE_GROUP_USERS "users"
#define AQH_SERVICE_FILE_GROUP_MODULES "modules"
#define AQH_SERVICE_FILE_GROUP_SESSIONS "sessions"
/* ------------------------------------------------------------------------------------------------
* global vars
* ------------------------------------------------------------------------------------------------
*/
GWEN_INHERIT(AQH_SERVICE, AQH_SERVICE_FILE)
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
static AQH_USER *_loadUser(AQH_SERVICE *sv, const char *s);
static int _saveUser(AQH_SERVICE *sv, AQH_USER *user);
static int _addUser(AQH_SERVICE *sv, AQH_USER *user);
static int _delUser(AQH_SERVICE *sv, const char *s);
static GWEN_STRINGLIST *_listUsers(AQH_SERVICE *sv);
static AQH_MODULE *_loadModule(AQH_SERVICE *sv, const char *s);
static int _saveModule(AQH_SERVICE *sv, AQH_MODULE *module);
static int _addModule(AQH_SERVICE *sv, AQH_MODULE *module);
static int _delModule(AQH_SERVICE *sv, const char *s);
static GWEN_STRINGLIST *_listModules(AQH_SERVICE *sv);
static AQH_SESSION* _loadSession(AQH_SERVICE *sv, const char *s);
static int _saveSession(AQH_SERVICE *sv, AQH_SESSION *session);
static int _addSession(AQH_SERVICE *sv, AQH_SESSION *session);
static int _delSession(AQH_SERVICE *sv, const char *s);
static GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv);
static GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName);
static int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
static int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
static int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName);
static GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName);
//static void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
/* ------------------------------------------------------------------------------------------------
* code
* ------------------------------------------------------------------------------------------------
*/
AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder)
{
AQH_SERVICE *sv;
AQH_SERVICE_FILE *xs;
GWEN_BUFFER *dbuf;
sv=AQH_Service_new();
GWEN_NEW_OBJECT(AQH_SERVICE_FILE, xs);
GWEN_INHERIT_SETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv, xs, _freeData);
xs->baseFolder=strdup(baseFolder);
AQH_Service_SetLoadUserFn(sv, _loadUser);
AQH_Service_SetSaveUserFn(sv, _saveUser);
AQH_Service_SetAddUserFn(sv, _addUser);
AQH_Service_SetDelUserFn(sv, _delUser);
AQH_Service_SetListUsersFn(sv, _listUsers);
AQH_Service_SetLoadModuleFn(sv, _loadModule);
AQH_Service_SetSaveModuleFn(sv, _saveModule);
AQH_Service_SetAddModuleFn(sv, _addModule);
AQH_Service_SetDelModuleFn(sv, _delModule);
AQH_Service_SetListModulesFn(sv, _listModules);
AQH_Service_SetLoadSessionFn(sv, _loadSession);
AQH_Service_SetSaveSessionFn(sv, _saveSession);
AQH_Service_SetAddSessionFn(sv, _addSession);
AQH_Service_SetDelSessionFn(sv, _delSession);
AQH_Service_SetListSessionsFn(sv, _listSessions);
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendArgs(dbuf, "dir://%s", baseFolder);
DBG_ERROR(NULL, "Creating config mgr \"%s\"", GWEN_Buffer_GetStart(dbuf));
xs->configMgr=GWEN_ConfigMgr_Factory(GWEN_Buffer_GetStart(dbuf));
if (xs->configMgr==NULL) {
DBG_ERROR(NULL, "Error creating config mgr \"%s\"", GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_free(dbuf);
AQH_Service_free(sv);
return NULL;
}
GWEN_Buffer_free(dbuf);
return sv;
}
void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
{
AQH_SERVICE_FILE *xs;
xs=(AQH_SERVICE_FILE*) p;
GWEN_ConfigMgr_free(xs->configMgr);
free(xs->baseFolder);
GWEN_FREE_OBJECT(xs);
}
AQH_USER *_loadUser(AQH_SERVICE *sv, const char *s)
{
GWEN_DB_NODE *db;
db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s);
if (db) {
AQH_USER *user;
user=AQH_User_fromDb(db);
GWEN_DB_Group_free(db);
return user;
}
return NULL;
}
int _saveUser(AQH_SERVICE *sv, AQH_USER *user)
{
const char *s;
s=AQH_User_GetAlias(user);
if (s && *s) {
GWEN_DB_NODE *db;
int rv;
db=GWEN_DB_Group_new(s);
rv=AQH_User_toDb(user, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
//_logGroup(AQH_SERVICE_FILE_GROUP_USERS, s, db);
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
GWEN_DB_Group_free(db);
return 0;
}
return GWEN_ERROR_INVALID;
}
int _addUser(AQH_SERVICE *sv, AQH_USER *user)
{
const char *s;
s=AQH_User_GetAlias(user);
if (s && *s) {
GWEN_DB_NODE *db;
int rv;
db=GWEN_DB_Group_new(s);
rv=AQH_User_toDb(user, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
GWEN_DB_Group_free(db);
return 0;
}
return GWEN_ERROR_INVALID;
}
int _delUser(AQH_SERVICE *sv, const char *s)
{
return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_USERS, s);
}
GWEN_STRINGLIST *_listUsers(AQH_SERVICE *sv)
{
return _listGroup(sv, AQH_SERVICE_FILE_GROUP_USERS);
}
AQH_MODULE *_loadModule(AQH_SERVICE *sv, const char *s)
{
GWEN_DB_NODE *db;
db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s);
if (db) {
AQH_MODULE *module;
module=AQH_Module_fromDb(db);
GWEN_DB_Group_free(db);
return module;
}
return NULL;
}
int _saveModule(AQH_SERVICE *sv, AQH_MODULE *module)
{
const char *s;
s=AQH_Module_GetName(module);
if (s && *s) {
GWEN_DB_NODE *db;
int rv;
db=GWEN_DB_Group_new(s);
rv=AQH_Module_toDb(module, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
GWEN_DB_Group_free(db);
return 0;
}
return GWEN_ERROR_INVALID;
}
int _addModule(AQH_SERVICE *sv, AQH_MODULE *module)
{
const char *s;
s=AQH_Module_GetName(module);
if (s && *s) {
GWEN_DB_NODE *db;
int rv;
db=GWEN_DB_Group_new(s);
rv=AQH_Module_toDb(module, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
GWEN_DB_Group_free(db);
return 0;
}
return GWEN_ERROR_INVALID;
}
int _delModule(AQH_SERVICE *sv, const char *s)
{
return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_MODULES, s);
}
GWEN_STRINGLIST *_listModules(AQH_SERVICE *sv)
{
return _listGroup(sv, AQH_SERVICE_FILE_GROUP_MODULES);
}
AQH_SESSION* _loadSession(AQH_SERVICE *sv, const char *s)
{
GWEN_DB_NODE *db;
db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s);
if (db) {
AQH_SESSION *session;
session=AQH_Session_fromDb(db);
GWEN_DB_Group_free(db);
return session;
}
return NULL;
}
int _saveSession(AQH_SERVICE *sv, AQH_SESSION *session)
{
const char *s;
s=AQH_Session_GetUid(session);
if (s && *s) {
GWEN_DB_NODE *db;
int rv;
db=GWEN_DB_Group_new(s);
rv=AQH_Session_toDb(session, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
GWEN_DB_Group_free(db);
return 0;
}
return GWEN_ERROR_INVALID;
}
int _addSession(AQH_SERVICE *sv, AQH_SESSION *session)
{
const char *s;
s=AQH_Session_GetUid(session);
if (s && *s) {
GWEN_DB_NODE *db;
int rv;
db=GWEN_DB_Group_new(s);
rv=AQH_Session_toDb(session, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
GWEN_DB_Group_free(db);
return rv;
}
GWEN_DB_Group_free(db);
return 0;
}
return GWEN_ERROR_INVALID;
}
int _delSession(AQH_SERVICE *sv, const char *s)
{
return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s);
}
GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv)
{
return _listGroup(sv, AQH_SERVICE_FILE_GROUP_SESSIONS);
}
GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName)
{
DBG_ERROR(NULL, "Lock and load group %s/%s", groupName, subGroupName);
if (sv && groupName && subGroupName) {
AQH_SERVICE_FILE *xs;
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
if (xs) {
GWEN_DB_NODE *db=NULL;
int rv;
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
return NULL;
}
DBG_ERROR(NULL, "Loading group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_GetGroup(xs->configMgr, groupName, subGroupName, &db);
if (rv<0) {
DBG_ERROR(NULL, "Error reading group \"%s/%s\": %d", groupName, subGroupName, rv);
GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
return NULL;
}
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
GWEN_DB_Group_free(db);
return NULL;
}
return db;
}
}
else {
DBG_ERROR(NULL, "Missing argument");
}
return NULL;
}
int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db)
{
if (sv && groupName && subGroupName && db) {
AQH_SERVICE_FILE *xs;
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
if (xs) {
int rv;
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
DBG_ERROR(NULL, "Writing group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
if (rv<0) {
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
return 0;
}
}
return GWEN_ERROR_INVALID;
}
int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db)
{
if (sv && groupName && subGroupName && db) {
AQH_SERVICE_FILE *xs;
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
if (xs) {
int rv;
rv=GWEN_ConfigMgr_HasGroup(xs->configMgr, groupName, subGroupName);
if (rv>=0) {
DBG_ERROR(NULL, "Group \"%s/%s\" already exists", groupName, subGroupName);
return GWEN_ERROR_FOUND;
}
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
if (rv<0) {
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
return 0;
}
}
return GWEN_ERROR_INVALID;
}
int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName)
{
if (sv && groupName && subGroupName) {
AQH_SERVICE_FILE *xs;
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
if (xs) {
int rv;
rv=GWEN_ConfigMgr_DeleteGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
return 0;
}
}
return GWEN_ERROR_INVALID;
}
GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName)
{
if (sv && groupName) {
AQH_SERVICE_FILE *xs;
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
if (xs) {
GWEN_STRINGLIST *sl;
int rv;
sl=GWEN_StringList_new();
rv=GWEN_ConfigMgr_ListSubGroups(xs->configMgr, groupName, sl);
if (rv<0) {
DBG_ERROR(NULL, "Error listing group \"%s\": %d", groupName, rv);
GWEN_StringList_free(sl);
return NULL;
}
if (GWEN_StringList_Count(sl)==0) {
GWEN_StringList_free(sl);
return NULL;
}
return sl;
}
}
return NULL;
}
#if 0
void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db)
{
if (db) {
GWEN_BUFFER *dbuf;
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_DB_WriteToBuffer(db, dbuf, GWEN_DB_FLAGS_DEFAULT);
DBG_ERROR(NULL, "Group %s/%s:\n%s", groupName?groupName:"<empty>", subGroupName?subGroupName:"<empty>",
GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_free(dbuf);
}
else {
DBG_ERROR(NULL, "Group %s/%s empty", groupName?groupName:"<empty>", subGroupName?subGroupName:"<empty>");
}
}
#endif

View File

@@ -0,0 +1,21 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_SERVICE_FILE_H
#define AQHOME_SERVICE_FILE_H
#include "aqhome-cgi/service/service.h"
AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder);
#endif

View File

@@ -6,24 +6,23 @@
* should have received along with this file.
****************************************************************************/
#ifndef AQH_ENDPOINT_MQTT_P_H
#define AQH_ENDPOINT_MQTT_P_H
#ifndef AQHOME_SERVICE_FILE_P_H
#define AQHOME_SERVICE_FILE_P_H
#include "aqhome/mqtt/endpoint_mqtt.h"
#include "aqhome-cgi/service_file.h"
#include <gwenhywfar/configmgr.h>
typedef struct AQH_ENDPOINT_MQTT AQH_ENDPOINT_MQTT;
struct AQH_ENDPOINT_MQTT {
char *clientId;
uint16_t lastPacketId;
uint16_t keepAliveTime;
typedef struct AQH_SERVICE_FILE AQH_SERVICE_FILE;
struct AQH_SERVICE_FILE {
char *baseFolder;
GWEN_CONFIGMGR *configMgr;
};
#endif

View File

@@ -120,8 +120,9 @@ int main(int argc, char **argv)
_runService(aqh, eventLoop);
//AqHomeData_Fini(aqh);
AqHomeDataServer_Fini(aqh);
AQH_Object_free(aqh);
AQH_EventLoop_free(eventLoop);
GWEN_Gui_SetGui(NULL);
GWEN_Gui_free(gui);

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -33,8 +33,8 @@
* ------------------------------------------------------------------------------------------------
*/
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 2048
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 1024
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 1024
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 512
/* ------------------------------------------------------------------------------------------------
@@ -44,13 +44,15 @@
static int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value,
int mode,
uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId);
static int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
static int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value,
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
uint32_t refMsgId);
static int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
static int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
static int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
static void _sendDataPointsResponse(AQH_OBJECT *ep, const AQH_VALUE *value, const uint64_t *tablePtr,
uint32_t refMsgId);
static void _getAndSendLastDatapoint(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint32_t refMsgId);
@@ -79,16 +81,18 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A
uint64_t tsBegin;
uint64_t tsEnd;
uint64_t numRequested;
int mode;
tsBegin=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0);
tsEnd=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0);
numRequested=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_NUM, 0);
mode=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_MODE, AQH_MSGDATA_GETDATA_MODE_FIRST);
value=AQH_Storage_GetValueByNameForSystem(xo->storage, valueName);
if (value) {
int resultCode;
resultCode=_getAndSendDataPoints(xo->storage, ep, value, tsBegin, tsEnd, numRequested, refMsgId);
resultCode=_getAndSendDataPoints(xo->storage, ep, value, mode, tsBegin, tsEnd, numRequested, refMsgId);
AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode);
}
else {
@@ -114,30 +118,31 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A
int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value,
int mode,
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
uint32_t refMsgId)
{
if (num==0)
return _getAndSendDataPointsNoNum(storage, ep, value, tsBegin, tsEnd, refMsgId);
else if (num==1) {
_getAndSendLastDatapoint(storage, ep, value, refMsgId);
return AQH_MSGDATA_RESULT_SUCCESS;
switch(mode) {
case AQH_MSGDATA_GETDATA_MODE_FIRST: return _getAndSendDataPointsFirst(storage, ep, value, num, refMsgId);
case AQH_MSGDATA_GETDATA_MODE_PERIOD: return _getAndSendDataPointsPeriod(storage, ep, value, tsBegin, tsEnd, num, refMsgId);
default:
case AQH_MSGDATA_GETDATA_MODE_LAST: return _getAndSendDataPointsLast(storage, ep, value, num, refMsgId);
}
else
return _getAndSendDataPointsWithNum(storage, ep, value, num, refMsgId);
}
int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
uint32_t refMsgId)
int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
uint32_t refMsgId)
{
uint64_t valueId;
uint64_t *tablePtr;
valueId=AQH_Value_GetId(value);
tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES);
if (num==0 || num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES)
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES;
tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, num);
if (tablePtr) {
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
free(tablePtr);
@@ -151,9 +156,9 @@ int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t num,
uint32_t refMsgId)
int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t num,
uint32_t refMsgId)
{
uint64_t valueId;
uint64_t *tablePtr;
@@ -175,6 +180,30 @@ int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t num,
uint32_t refMsgId)
{
uint64_t valueId;
uint64_t *tablePtr;
if (num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS)
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS;
valueId=AQH_Value_GetId(value);
tablePtr=AQH_Storage_GetFirstNDataPoints(storage, valueId, num);
if (tablePtr) {
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
free(tablePtr);
return AQH_MSGDATA_RESULT_SUCCESS;
}
else {
DBG_INFO(NULL, "No matching datapoints for value \"%s\"", AQH_Value_GetNameForSystem(value));
return AQH_MSGDATA_RESULT_ERROR_NODATA;
}
}
void _sendDataPointsResponse(AQH_OBJECT *ep,
const AQH_VALUE *value, const uint64_t *tablePtr,
uint32_t refMsgId)
@@ -193,36 +222,3 @@ void _sendDataPointsResponse(AQH_OBJECT *ep,
void _getAndSendLastDatapoint(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint32_t refMsgId)
{
int rv;
uint64_t timestamp=0;
double data=0.0;
rv=AQH_Storage_GetLastDataPoint(storage, AQH_Value_GetId(value), &timestamp, &data);
if (rv<0) {
int resultCode;
switch(rv) {
case GWEN_ERROR_INVALID: resultCode=AQH_MSGDATA_RESULT_ERROR_INVALID; break;
case GWEN_ERROR_NO_DATA: resultCode=AQH_MSGDATA_RESULT_ERROR_NODATA; break;
default: resultCode=AQH_MSGDATA_RESULT_ERROR_GENERIC; break;
}
AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode);
}
else {
AQH_MESSAGE *outMsg;
outMsg=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP,
AQH_Endpoint_GetNextMessageId(ep), refMsgId,
value, timestamp, data);
AQH_Endpoint_AddMsgOut(ep, outMsg);
}
}

View File

@@ -47,59 +47,57 @@ static void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t
* ------------------------------------------------------------------------------------------------
*/
void AqHomeDataServer_HandleGetDevices(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList)
void AqHomeDataServer_HandleGetDevices(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, GWEN_UNUSED const GWEN_TAG16_LIST *tagList)
{
if (tagList) {
AQHOME_SERVER *xo;
xo=AqHomeDataServer_GetServerData(o);
if (xo) {
const AQH_DEVICE_LIST *origDeviceList;
uint32_t refMsgId;
refMsgId=AQH_IpcMessage_GetMsgId(msg);
DBG_ERROR(NULL, "HandleGetDevices");
origDeviceList=AQH_Storage_GetDeviceList(xo->storage);
if (origDeviceList) {
DBG_ERROR(NULL, "Have a list of %d devices", AQH_Device_List_GetCount(origDeviceList));
if (AQH_Device_List_GetCount(origDeviceList)<AQHOMEDATA_DEVICESPERMSG) {
DBG_ERROR(NULL, "Sending all entries in one message");
_sendDeviceList(ep, origDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
}
else {
AQH_DEVICE_LIST *tmpDeviceList;
const AQH_DEVICE *v;
DBG_INFO(NULL, "Sending entries in multiple messages");
tmpDeviceList=AQH_Device_List_new();
v=AQH_Device_List_First(origDeviceList);
while(v) {
const AQH_DEVICE *next;
AQH_DEVICE *copyOfDevice;
next=AQH_Device_List_Next(v);
copyOfDevice=AQH_Device_dup(v);
AQH_Device_List_Add(copyOfDevice, tmpDeviceList);
if (AQH_Device_List_GetCount(tmpDeviceList)>=AQHOMEDATA_DEVICESPERMSG) {
DBG_ERROR(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
_sendDeviceList(ep, tmpDeviceList, next?0:AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
AQH_Device_List_Clear(tmpDeviceList);
}
v=next;
}
if (AQH_Device_List_GetCount(tmpDeviceList)) {
DBG_ERROR(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
_sendDeviceList(ep, tmpDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId); /* send remaining */
}
AQH_Device_List_free(tmpDeviceList);
}
AQHOME_SERVER *xo;
xo=AqHomeDataServer_GetServerData(o);
if (xo) {
const AQH_DEVICE_LIST *origDeviceList;
uint32_t refMsgId;
refMsgId=AQH_IpcMessage_GetMsgId(msg);
DBG_INFO(NULL, "HandleGetDevices");
origDeviceList=AQH_Storage_GetDeviceList(xo->storage);
if (origDeviceList) {
DBG_INFO(NULL, "Have a list of %d devices", AQH_Device_List_GetCount(origDeviceList));
if (AQH_Device_List_GetCount(origDeviceList)<AQHOMEDATA_DEVICESPERMSG) {
DBG_INFO(NULL, "Sending all entries in one message");
_sendDeviceList(ep, origDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
}
else {
/* empty list */
_sendDeviceList(ep, NULL, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
AQH_DEVICE_LIST *tmpDeviceList;
const AQH_DEVICE *v;
DBG_INFO(NULL, "Sending entries in multiple messages");
tmpDeviceList=AQH_Device_List_new();
v=AQH_Device_List_First(origDeviceList);
while(v) {
const AQH_DEVICE *next;
AQH_DEVICE *copyOfDevice;
next=AQH_Device_List_Next(v);
copyOfDevice=AQH_Device_dup(v);
AQH_Device_List_Add(copyOfDevice, tmpDeviceList);
if (AQH_Device_List_GetCount(tmpDeviceList)>=AQHOMEDATA_DEVICESPERMSG) {
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
_sendDeviceList(ep, tmpDeviceList, next?0:AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
AQH_Device_List_Clear(tmpDeviceList);
}
v=next;
}
if (AQH_Device_List_GetCount(tmpDeviceList)) {
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
_sendDeviceList(ep, tmpDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId); /* send remaining */
}
AQH_Device_List_free(tmpDeviceList);
}
}
else {
/* empty list */
_sendDeviceList(ep, NULL, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
}
}
}
@@ -109,7 +107,7 @@ void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags,
{
AQH_MESSAGE *msg;
DBG_ERROR(NULL, "Sending msg (refMsgId=%d)", refMsgId);
DBG_INFO(NULL, "Sending msg (refMsgId=%d)", refMsgId);
msg=AQH_IpcdMessageDevices_new(AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP, AQH_Endpoint_GetNextMessageId(ep), refMsgId, flags, vl);
AQH_Endpoint_AddMsgOut(ep, msg);
}

View File

@@ -13,13 +13,16 @@
#include "./s_getvalues.h"
#include "./server_p.h"
#include "aqhome/aqhome.h"
#include "aqhome/ipc2/endpoint.h"
#include "aqhome/msg/ipc/m_ipc.h"
#include "aqhome/msg/ipc/data/m_ipcd.h"
#include "aqhome/msg/ipc/data/m_ipcd_getvalues.h"
#include "aqhome/msg/ipc/data/m_ipcd_values.h"
#include "aqhome/msg/ipc/m_ipc_result.h"
#include "aqhome/msg/ipc/m_ipc_tag16.h"
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
@@ -38,7 +41,10 @@
* ------------------------------------------------------------------------------------------------
*/
static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId);
static AQH_VALUE_LIST *_getMatchingValueList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList);
static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t refMsgId);
static void _sendValueListMsg(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId);
static int _valueMatches(const AQH_VALUE *v, const char *deviceName, int modality);
@@ -49,71 +55,129 @@ static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t fl
void AqHomeDataServer_HandleGetValues(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList)
{
if (tagList) {
AQHOME_SERVER *xo;
xo=AqHomeDataServer_GetServerData(o);
if (xo) {
const AQH_VALUE_LIST *origValueList;
uint32_t refMsgId;
refMsgId=AQH_IpcMessage_GetMsgId(msg);
DBG_INFO(NULL, "HandleGetValues");
origValueList=AQH_Storage_GetValueList(xo->storage);
if (origValueList) {
DBG_INFO(NULL, "Have a list of %d values", AQH_Value_List_GetCount(origValueList));
if (AQH_Value_List_GetCount(origValueList)<AQHOMEDATA_VALUESPERMSG) {
DBG_INFO(NULL, "Sending all entries in one message");
_sendValueList(ep, origValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
}
else {
AQH_VALUE_LIST *tmpValueList;
const AQH_VALUE *v;
DBG_INFO(NULL, "Sending entries in multiple messages");
tmpValueList=AQH_Value_List_new();
v=AQH_Value_List_First(origValueList);
while(v) {
const AQH_VALUE *next;
AQH_VALUE *copyOfValue;
next=AQH_Value_List_Next(v);
copyOfValue=AQH_Value_dup(v);
AQH_Value_List_Add(copyOfValue, tmpValueList);
if (AQH_Value_List_GetCount(tmpValueList)>=AQHOMEDATA_VALUESPERMSG) {
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
_sendValueList(ep, tmpValueList, next?0:AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
AQH_Value_List_Clear(tmpValueList);
}
v=next;
}
if (AQH_Value_List_GetCount(tmpValueList)) {
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
_sendValueList(ep, tmpValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); /* send remaining */
}
AQH_Value_List_free(tmpValueList);
}
}
else {
/* empty list */
_sendValueList(ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
}
AQHOME_SERVER *xo;
xo=AqHomeDataServer_GetServerData(o);
if (xo) {
AQH_VALUE_LIST *valueList;
uint32_t refMsgId;
refMsgId=AQH_IpcMessage_GetMsgId(msg);
DBG_INFO(NULL, "HandleGetValues");
valueList=_getMatchingValueList(xo, tagList);
if (valueList) {
_sendValueList(ep, valueList, refMsgId);
AQH_Value_List_free(valueList);
}
else {
/* empty list */
_sendValueListMsg(ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
}
}
}
void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId)
AQH_VALUE_LIST *_getMatchingValueList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList)
{
const AQH_VALUE_LIST *origValueList;
AQH_VALUE_LIST *tmpValueList=NULL;
char *deviceName;
int modality;
deviceName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETVALUES_TAGS_DEVICENAME, NULL):NULL;
modality=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETVALUES_TAGS_MODALITY, 0):0;
origValueList=AQH_Storage_GetValueList(xo->storage);
if (origValueList) {
const AQH_VALUE *v;
tmpValueList=AQH_Value_List_new();
v=AQH_Value_List_First(origValueList);
while(v) {
if (_valueMatches(v, deviceName, modality)) {
AQH_VALUE *copyOfValue;
copyOfValue=AQH_Value_dup(v);
AQH_Value_List_Add(copyOfValue, tmpValueList);
}
v=AQH_Value_List_Next(v);
}
if (AQH_Value_List_GetCount(tmpValueList)<1) {
AQH_Value_List_free(tmpValueList);
tmpValueList=NULL;
}
}
free(deviceName);
return tmpValueList;
}
void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t refMsgId)
{
AQH_VALUE_LIST *tmpValueList;
const AQH_VALUE *v;
tmpValueList=AQH_Value_List_new();
v=AQH_Value_List_First(vl);
while(v) {
const AQH_VALUE *next;
AQH_VALUE *copyOfValue;
next=AQH_Value_List_Next(v);
copyOfValue=AQH_Value_dup(v);
AQH_Value_List_Add(copyOfValue, tmpValueList);
if (AQH_Value_List_GetCount(tmpValueList)>=AQHOMEDATA_VALUESPERMSG) {
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
_sendValueListMsg(ep, tmpValueList, next?0:AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
AQH_Value_List_Clear(tmpValueList);
}
v=next;
}
if (AQH_Value_List_GetCount(tmpValueList)) {
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
_sendValueListMsg(ep, tmpValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); /* send remaining */
}
AQH_Value_List_free(tmpValueList);
}
void _sendValueListMsg(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId)
{
AQH_MESSAGE *msg;
DBG_ERROR(NULL, "Sending msg (refMsgId=%d)", refMsgId);
DBG_INFO(NULL, "Sending msg (refMsgId=%d)", refMsgId);
msg=AQH_IpcdMessageValues_new(AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP, AQH_Endpoint_GetNextMessageId(ep), refMsgId, flags, vl);
AQH_Endpoint_AddMsgOut(ep, msg);
}
int _valueMatches(const AQH_VALUE *v, const char *deviceName, int modality)
{
if (modality!=AQH_ValueModality_Unknown) {
int valModality;
valModality=AQH_Value_GetModality(v);
if (valModality!=modality)
return 0;
}
if (deviceName && *deviceName) {
const char *s;
s=AQH_Value_GetDeviceNameForSystem(v);
if (s && *s && GWEN_Text_ComparePattern(s, deviceName, 0)==-1)
return 0;
}
return 1;
}

View File

@@ -126,6 +126,7 @@ void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
}
GWEN_DB_Group_free(xo->dbArgs);
AQH_Storage_free(xo->storage);
AQH_MsgRequest_free(xo->requestTree);
free(xo->pidFile);
GWEN_FREE_OBJECT(xo);
@@ -304,6 +305,24 @@ int _setupIpc(AQH_OBJECT *o, AQHOME_SERVER *xo, GWEN_DB_NODE *dbArgs)
/* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* fini
* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
*/
void AqHomeDataServer_Fini(AQH_OBJECT *o)
{
AQHOME_SERVER *xo;
xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQHOME_SERVER, o);
if (xo) {
if (xo->pidFile)
remove(xo->pidFile);
}
}
/* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* signal handler
* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@@ -329,7 +348,7 @@ int _handleNewClient(AQH_OBJECT *o, AQH_OBJECT *clientEndpoint)
xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQHOME_SERVER, o);
if (xo) {
DBG_ERROR(NULL, "New IPC client");
DBG_INFO(NULL, "New IPC client");
AQH_Object_AddLink(clientEndpoint, AQH_ENDPOINT_SIGNAL_CLOSED, AQH_AQHOME_SERVER_SLOT_CLOSED, o);
AQH_Object_List_Add(clientEndpoint, xo->tcpClientList);
return 1; /* handled */
@@ -346,7 +365,7 @@ int _handleClientDown(AQH_OBJECT *o, AQH_OBJECT *clientEndpoint)
xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQHOME_SERVER, o);
if (xo) {
DBG_ERROR(NULL, "IPC client down");
DBG_INFO(NULL, "IPC client down");
AQH_Object_AddFlags(clientEndpoint, AQH_OBJECT_FLAGS_DELETE);
return 1; /* handled */
}

View File

@@ -33,6 +33,7 @@
AQH_OBJECT *AqHomeDataServer_new(AQH_EVENT_LOOP *eventLoop);
int AqHomeDataServer_Init(AQH_OBJECT *o, int argc, char **argv);
void AqHomeDataServer_Fini(AQH_OBJECT *o);
int AqHomeDataServer_GetTimeout(const AQH_OBJECT *o);
int AqHomeDataServer_GetClientNum(const AQH_OBJECT *o);

View File

@@ -130,6 +130,7 @@ int main(int argc, char **argv)
AQH_MqttLogServer_Fini(aqh);
AQH_Object_free(aqh);
AQH_EventLoop_free(eventLoop);
GWEN_Gui_SetGui(NULL);
GWEN_Gui_free(gui);

View File

@@ -31,7 +31,7 @@
* ------------------------------------------------------------------------------------------------
*/
static int _handlePublish(AQH_OBJECT *o, const char *rcvdTopic, const char *rcvdValue);
static int _handlePublish(AQH_OBJECT *o, AQH_MQTTLOG_SERVER *xo, const char *rcvdTopic, const char *rcvdValue);
static void _handleNumTopic(AQH_MQTTLOG_SERVER *xo, AQHMQTT_DEVICE *device,
AQHMQTT_TOPIC *topic, const char *rcvdValue);
static void _handleJsonTopic(AQH_MQTTLOG_SERVER *xo, AQHMQTT_DEVICE *device,
@@ -69,12 +69,12 @@ void AQH_MqttLogServer_HandlePublishMsg(AQH_OBJECT *o, GWEN_UNUSED AQH_OBJECT *e
if (topic && value) {
int rv;
rv=_handlePublish(o, topic, value);
rv=_handlePublish(o, xo, topic, value);
if (rv!=1) {
DBG_INFO(NULL, "New topic \"%s\", trying to register", topic);
rv=_registerNewDeviceForTopic(xo, topic);
if (rv==1) {
rv=_handlePublish(o, topic, value);
rv=_handlePublish(o, xo, topic, value);
if (rv!=1) {
DBG_ERROR(NULL, "Topic \"%s\" still not handled, SNH!", topic);
}
@@ -92,53 +92,48 @@ void AQH_MqttLogServer_HandlePublishMsg(AQH_OBJECT *o, GWEN_UNUSED AQH_OBJECT *e
int _handlePublish(AQH_OBJECT *o, const char *rcvdTopic, const char *rcvdValue)
int _handlePublish(AQH_OBJECT *o, AQH_MQTTLOG_SERVER *xo, const char *rcvdTopic, const char *rcvdValue)
{
if (o && rcvdTopic && *rcvdTopic) {
AQH_MQTTLOG_SERVER *xo;
if (o && rcvdTopic && *rcvdTopic && xo && xo->registeredDeviceList) {
AQHMQTT_DEVICE *device;
xo=AQH_MqttLogServer_GetServerData(o);
if (xo && xo->registeredDeviceList) {
AQHMQTT_DEVICE *device;
device=AQHMQTT_Device_List_First(xo->registeredDeviceList);
while(device) {
AQHMQTT_TOPIC_LIST *topicList;
const char *sDeviceName;
const char *sDeviceId;
device=AQHMQTT_Device_List_First(xo->registeredDeviceList);
while(device) {
AQHMQTT_TOPIC_LIST *topicList;
const char *sDeviceName;
const char *sDeviceId;
sDeviceName=AQHMQTT_Device_GetName(device);
sDeviceId=AQHMQTT_Device_GetId(device);
sDeviceName=AQHMQTT_Device_GetName(device);
sDeviceId=AQHMQTT_Device_GetId(device);
topicList=AQHMQTT_Device_GetTopicList(device);
if (topicList) {
AQHMQTT_TOPIC *topic;
topicList=AQHMQTT_Device_GetTopicList(device);
if (topicList) {
AQHMQTT_TOPIC *topic;
topic=_findTopicMatchingTopic(topicList, rcvdTopic, AQHMQTT_TopicDir_In);
topic=_findTopicMatchingTopic(topicList, rcvdTopic, AQHMQTT_TopicDir_In);
#if 0
if (topic==NULL) {
topic=_findMaskMatchingTopic(topicList, rcvdTopic, AQHMQTT_TopicDir_In);
if (topic)
AQHMQTT_Topic_SetTopic(topic, rcvdTopic);
}
#endif
if (topic) {
DBG_INFO(AQH_LOGDOMAIN,
"Handling topic \"%s\" for device type %s (id: %s)",
rcvdTopic,
sDeviceName, sDeviceId?sDeviceId:"<no id>");
if (AQHMQTT_Topic_GetTopicType(topic)==AQHMQTT_TopicType_Json)
_handleJsonTopic(xo, device, topic, rcvdValue);
else
_handleNumTopic(xo, device, topic, rcvdValue);
return 1;
}
if (topic==NULL) {
topic=_findMaskMatchingTopic(topicList, rcvdTopic, AQHMQTT_TopicDir_In);
if (topic)
AQHMQTT_Topic_SetTopic(topic, rcvdTopic);
}
#endif
if (topic) {
DBG_INFO(AQH_LOGDOMAIN,
"Handling topic \"%s\" for device type %s (id: %s)",
rcvdTopic,
sDeviceName, sDeviceId?sDeviceId:"<no id>");
if (AQHMQTT_Topic_GetTopicType(topic)==AQHMQTT_TopicType_Json)
_handleJsonTopic(xo, device, topic, rcvdValue);
else
_handleNumTopic(xo, device, topic, rcvdValue);
return 1;
}
device=AQHMQTT_Device_List_Next(device);
}
DBG_INFO(AQH_LOGDOMAIN, "ignoring topic \"%s\"", rcvdTopic);
device=AQHMQTT_Device_List_Next(device);
}
DBG_INFO(AQH_LOGDOMAIN, "ignoring topic \"%s\"", rcvdTopic);
}
return 0;
}
@@ -282,7 +277,7 @@ void _sendAnnounceValueMessage(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *dev
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0,
0, msgValue);
if (pubMsg) {
DBG_INFO(AQH_LOGDOMAIN, "BROKER ANNOUNCE_VALUE %s", AQH_Value_GetName(msgValue));
DBG_ERROR(AQH_LOGDOMAIN, "BROKER ANNOUNCE_VALUE %s/%s", AQH_Value_GetDeviceName(msgValue), AQH_Value_GetName(msgValue));
AQH_Endpoint_AddMsgOut(xo->brokerEndpoint, pubMsg);
}
AQH_Value_free(msgValue);

View File

@@ -10,7 +10,7 @@
#define AQHOMEMQTT_S_PUBLISH_H
#include "./aqhome_mqtt.h"
#include "./server.h"
#include <aqhome/events2/object.h>
#include <aqhome/ipc2/message.h>

View File

@@ -20,7 +20,7 @@
#include <gwenhywfar/debug.h>
#define DEBUG_DRY_RUN 1 /* don't actually set value if "1" */
#define DEBUG_DRY_RUN 0 /* don't actually set value if "1" */
@@ -31,8 +31,7 @@
static void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device,
const char *valueName, const char *valueData);
static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId,
const AQHMQTT_TOPIC *topic, const char *valueData);
static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData);
static GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic);
@@ -131,7 +130,7 @@ void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo,
void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData)
void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData)
{
GWEN_BUFFER *buf;
#if !DEBUG_DRY_RUN

View File

@@ -10,7 +10,7 @@
#define AQHOMEMQTT_S_SETDATA_H
#include "./aqhome_mqtt.h"
#include "./server.h"
#include <aqhome/events2/object.h>
#include <aqhome/ipc2/message.h>

View File

@@ -109,10 +109,10 @@ static int _handleSignal(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObjec
static int _handleBrokerDown(AQH_MQTTLOG_SERVER *xo);
static int _handleMqttDown(AQH_MQTTLOG_SERVER *xo);
static void _handleMsgFromBroker(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg);
static void _handleMsgFromBroker(AQH_OBJECT *o, const AQH_MESSAGE *msg);
static void _handleMsgFromMqtt(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg);
static void _handleMqttMsgPingRsp(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg);
static void _handleMqttMsgPingRsp(void);
static int _createPidFile(const char *pidFilename);
static int _diffInSeconds(time_t t1, time_t t0);
@@ -156,8 +156,15 @@ void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
AQH_Object_free(xo->mqttEndpoint);
AQH_Object_free(xo->brokerEndpoint);
AQHMQTT_Device_List_free(xo->availableDeviceList);
AQHMQTT_Device_List_free(xo->registeredDeviceList);
GWEN_DB_Group_free(xo->dbArgs);
free(xo->deviceFile);
free(xo->pidFile);
free(xo->mqttAddress);
free(xo->mqttClientId);
free(xo->brokerAddress);
free(xo->brokerClientId);
GWEN_FREE_OBJECT(xo);
}
@@ -474,7 +481,7 @@ int _startBroker(AQH_OBJECT *o, AQH_MQTTLOG_SERVER *xo)
DBG_ERROR(NULL, "Error connecting to broker: %d", rv);
return (rv<0)?rv:GWEN_ERROR_PERMISSIONS;
}
DBG_NOTICE(NULL, "Connected to broker at %s:%d", xo->brokerAddress, xo->brokerPort);
DBG_NOTICE(NULL, "Fully connected to broker at %s:%d", xo->brokerAddress, xo->brokerPort);
return 0;
}
else {
@@ -658,7 +665,7 @@ void AQH_MqttLogServer_HandleBrokerMsgs(AQH_OBJECT *o)
while( (msg=AQH_Endpoint_GetNextMsgIn(xo->brokerEndpoint)) ) {
AQH_Message_SetObject(msg, xo->brokerEndpoint);
_handleMsgFromBroker(o, xo->brokerEndpoint, msg);
_handleMsgFromBroker(o, msg);
AQH_Message_free(msg);
}
}
@@ -666,7 +673,7 @@ void AQH_MqttLogServer_HandleBrokerMsgs(AQH_OBJECT *o)
void _handleMsgFromBroker(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg)
void _handleMsgFromBroker(AQH_OBJECT *o, const AQH_MESSAGE *msg)
{
GWEN_TAG16_LIST *tagList;
@@ -762,14 +769,14 @@ void _handleMsgFromMqtt(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg)
code=AQH_MqttMessage_GetTypeAndFlags(msg);
switch(code & 0xf0) {
case (AQH_MQTTMSG_MSGTYPE_PUBLISH & 0xf0): AQH_MqttLogServer_HandlePublishMsg(o, ep, msg); break;
case (AQH_MQTTMSG_MSGTYPE_PINGRESP & 0xf0): _handleMqttMsgPingRsp(o, ep, msg); break;
case (AQH_MQTTMSG_MSGTYPE_PINGRESP & 0xf0): _handleMqttMsgPingRsp(); break;
default: break;
}
}
void _handleMqttMsgPingRsp(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg)
void _handleMqttMsgPingRsp(void)
{
DBG_INFO(NULL, "PING response received");
}
@@ -962,8 +969,9 @@ void AQH_MqttLogServer_LoadRuntimeDeviceFiles(AQH_OBJECT *o)
DBG_INFO(NULL, "Loading registered devices from file \"%s\"", xo->deviceFile);
deviceList=AQH_MqttLogServer_ReadDeviceFile(o, xo->deviceFile);
if (deviceList)
AQH_MqttLogServer_SetRegisteredDeviceList(o, deviceList);
if (deviceList==NULL)
deviceList=AQHMQTT_Device_List_new();
AQH_MqttLogServer_SetRegisteredDeviceList(o, deviceList);
}
}
}
@@ -999,7 +1007,7 @@ int AQH_MqttLogServer_SaveRuntimeDeviceFiles(AQH_OBJECT *o)
* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
*/
int _handleSignal(AQH_OBJECT *o, uint32_t slotId, AQH_OBJECT *senderObject, GWEN_UNUSED int param1, void *param2)
int _handleSignal(AQH_OBJECT *o, uint32_t slotId, GWEN_UNUSED AQH_OBJECT *senderObject, GWEN_UNUSED int param1, GWEN_UNUSED void *param2)
{
AQH_MQTTLOG_SERVER *xo;
@@ -1100,11 +1108,11 @@ int _readArgs(int argc, char **argv, GWEN_DB_NODE *dbArgs)
{ A_ARG, A_CHAR, "loglevel", 0, 1, "L", "loglevel", I18S("Specify loglevel"), NULL},
{ A_ARG, A_CHAR, "cfgdir", 0, 1, "D", "cfgdir", I18S("Specify the configuration folder"), NULL},
{ A_ARG, A_CHAR, "charset", 0, 1, NULL, "charset", I18S("Specify the output character set"), NULL},
{ A_ARG, A_CHAR, "mqttAddress", 0, 1, "t", "mqttaddress", I18S("Address of MQTT server"), NULL},
{ A_ARG, A_INT, "mqttPort", 0, 1, "P", "mqttport", I18S("Port of MQTT server (default: 1883)"), NULL},
{ A_ARG, A_CHAR, "mqttAddress", 0, 1, "ma", "mqttaddress", I18S("Address of MQTT server"), NULL},
{ A_ARG, A_INT, "mqttPort", 0, 1, "mp", "mqttport", I18S("Port of MQTT server (default: 1883)"), NULL},
{ A_ARG, A_CHAR, "mqttClientId", 0, 1, NULL, "mqttclientid", I18S("MQTT client id"), NULL},
{ A_ARG, A_INT, "mqttKeepAlive", 0, 1, "P", "mqttkeepalive", I18S("MQTT keep-alive time"), NULL},
{ A_ARG, A_CHAR, "brokerAddress", 0, 1, "ba", "brokerddress", I18S("Broker address [127.0.0.1]"), NULL},
{ A_ARG, A_CHAR, "brokerAddress", 0, 1, "ba", "brokeraddress", I18S("Broker address [127.0.0.1]"), NULL},
{ A_ARG, A_INT, "brokerPort", 0, 1, "bp", "brokerport", I18S("Broker port [1899]"), NULL},
{ A_ARG, A_CHAR, "brokerClientId", 0, 1, NULL, "brokerclientid", I18S("Broker client id"), NULL},
{ A_ARG, A_CHAR, "deviceFile", 0, 1, "d", "devicefile", I18S("Device file"), NULL},

View File

@@ -80,7 +80,7 @@ AQHMQTT_DEVICE_LIST *AQH_MqttLogServer_ReadDeviceFile(AQH_OBJECT *o, const char
deviceList=AQHMQTT_Device_List_new();
rv=_readDeviceFileToList(sFilename, deviceList);
if (rv<0) {
DBG_ERROR(NULL, "File \"%s\" not found", sFilename);
DBG_ERROR(NULL, "Could not read file \"%s\" (empty?)", sFilename);
AQHMQTT_Device_List_free(deviceList);
return NULL;
}

View File

@@ -10,7 +10,6 @@
#define AQHOME_MQTTLOG_XMLREAD_H
#include "aqhome-mqttlog/server.h"
#include "aqhome-mqttlog/aqhome_mqtt.h"
#include "aqhome-mqttlog/types/device.h"

View File

@@ -11,7 +11,6 @@
#endif
#include "./xmlwrite.h"
#include "./aqhome_mqtt_p.h"
#include "aqhome-mqttlog/types/topic.h"
#include "aqhome-mqttlog/types/value.h"
#include "aqhome-mqttlog/types/translation.h"

View File

@@ -10,7 +10,6 @@
#define AQHOME_MQTTLOG_XMLWRITE_H
#include "aqhome-mqttlog/server.h"
#include "aqhome-mqttlog/aqhome_mqtt.h"
#include "aqhome-mqttlog/types/device.h"

View File

@@ -44,6 +44,8 @@
r_forward.h
r_setaccmsggrps.h
r_getnodes.h
server.h
server_p.h
</headers>
<sources>

View File

@@ -117,6 +117,26 @@ void _handleMsgValue(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg)
if (ni==NULL) {
DBG_INFO(AQH_LOGDOMAIN, "Error handling message");
}
else {
uint8_t valueId;
uint16_t val;
val=AQH_ValueMessage_GetValueNom(msg);
valueId=AQH_ValueMessage_GetValueId(msg);
switch(valueId) {
case AQH_ENDPOINT_VID_STATS_PACKETS_IN: AQH_NodeInfo_SetStatsPacketsIn(ni, val); AQH_NodeDb_SetModified(xo->nodeDb); break;
case AQH_ENDPOINT_VID_STATS_PACKETS_OUT: AQH_NodeInfo_SetStatsPacketsOut(ni, val); AQH_NodeDb_SetModified(xo->nodeDb); break;
case AQH_ENDPOINT_VID_STATS_ERRS_CONTENT: AQH_NodeInfo_SetStatsCrcErrors(ni, val); AQH_NodeDb_SetModified(xo->nodeDb); break;
case AQH_ENDPOINT_VID_STATS_ERRS_IO: AQH_NodeInfo_SetStatsIoErrors(ni, val); AQH_NodeDb_SetModified(xo->nodeDb); break;
case AQH_ENDPOINT_VID_STATS_ERRS_NOBUF: break;
case AQH_ENDPOINT_VID_STATS_ERRS_COLLISIONS: AQH_NodeInfo_SetStatsCollisions(ni, val); AQH_NodeDb_SetModified(xo->nodeDb); break;
case AQH_ENDPOINT_VID_STATS_ERRS_BUSY: AQH_NodeInfo_SetStatsBusy(ni, val); AQH_NodeDb_SetModified(xo->nodeDb); break;
case AQH_ENDPOINT_VID_STATS_HEAP_USED: break;
case AQH_ENDPOINT_VID_STATS_HEAP_FREE: break;
default:
}
}
}
@@ -145,11 +165,13 @@ void _handleMsgComSendStat(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg)
if (ni==NULL) {
DBG_INFO(AQH_LOGDOMAIN, "Error handling message");
}
AQH_NodeInfo_SetStatsPacketsOut(ni, AQH_SendStatsMessage_GetPacketsOut(msg));
AQH_NodeInfo_SetStatsCollisions(ni, AQH_SendStatsMessage_GetCollisions(msg));
AQH_NodeInfo_SetStatsBusy(ni, AQH_SendStatsMessage_GetBusyErrors(msg));
AQH_NodeDb_SetModified(xo->nodeDb);
_updateTimestampLastChange(ni);
else {
AQH_NodeInfo_SetStatsPacketsOut(ni, AQH_SendStatsMessage_GetPacketsOut(msg));
AQH_NodeInfo_SetStatsCollisions(ni, AQH_SendStatsMessage_GetCollisions(msg));
AQH_NodeInfo_SetStatsBusy(ni, AQH_SendStatsMessage_GetBusyErrors(msg));
AQH_NodeDb_SetModified(xo->nodeDb);
_updateTimestampLastChange(ni);
}
}
@@ -258,22 +280,24 @@ void _setDeviceName(AQH_VALUE *value, uint32_t uid)
void _announceValue(AQH_NODE_SERVER *xo, uint32_t uid, const AQHNODE_VALUE *v)
{
AQH_VALUE *value;
AQH_MESSAGE *msg;
value=AQH_Value_new();
_setDeviceName(value, uid);
AQH_Value_SetDriver(value, "nodes");
AQH_Value_SetName(value, AQHNODE_Value_GetName(v));
AQH_Value_SetValueUnits(value, AQHNODE_Value_GetValueUnits(v));
AQH_Value_SetValueType(value, AQHNODE_Value_GetValueType(v));
AQH_Value_SetModality(value, AQHNODE_Value_GetModality(v));
if (xo && xo->brokerEndpoint) {
AQH_VALUE *value;
AQH_MESSAGE *msg;
msg=AQH_IpcdMessageValues_newForOne(AQH_MSGTYPE_IPC_DATA_ANNOUNCEVALUE,
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0,
0, value);
AQH_Endpoint_AddMsgOut(xo->brokerEndpoint, msg);
AQH_Value_free(value);
value=AQH_Value_new();
_setDeviceName(value, uid);
AQH_Value_SetDriver(value, "nodes");
AQH_Value_SetName(value, AQHNODE_Value_GetName(v));
AQH_Value_SetValueUnits(value, AQHNODE_Value_GetValueUnits(v));
AQH_Value_SetValueType(value, AQHNODE_Value_GetValueType(v));
AQH_Value_SetModality(value, AQHNODE_Value_GetModality(v));
msg=AQH_IpcdMessageValues_newForOne(AQH_MSGTYPE_IPC_DATA_ANNOUNCEVALUE,
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0,
0, value);
AQH_Endpoint_AddMsgOut(xo->brokerEndpoint, msg);
AQH_Value_free(value);
}
}

View File

@@ -115,8 +115,9 @@ int main(int argc, char **argv)
_runService(aqh, eventLoop);
//AQH_NodeServer_Fini(aqh);
AQH_NodeServer_Fini(aqh);
AQH_Object_free(aqh);
AQH_EventLoop_free(eventLoop);
GWEN_Gui_SetGui(NULL);
GWEN_Gui_free(gui);
@@ -149,13 +150,13 @@ void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop)
now=time(NULL);
if (_diffInSeconds(now, timeLastConnectionCleanup)>CONNCLEAN_INTERVAL_IN_SECS) {
DBG_ERROR(NULL, "Cleanup connections");
DBG_INFO(NULL, "Cleanup connections");
AQH_NodeServer_CleanupClients(aqh);
timeLastConnectionCleanup=now;
}
if (_diffInSeconds(now, timeLastConnCheck)>CONNCHECK_INTERVAL_IN_SECS) {
DBG_ERROR(NULL, "Check connections");
DBG_INFO(NULL, "Check connections");
AQH_NodeServer_CheckBrokerConnection(aqh);
AQH_NodeServer_CheckTtyConnection(aqh);
timeLastConnCheck=now;

View File

@@ -20,6 +20,7 @@
#include "aqhome/msg/ipc/m_ipc_connect.h"
#include "aqhome/msg/ipc/m_ipc_result.h"
#include "aqhome/msg/ipc/m_ipc_tag16.h"
#include <aqhome/msg/node/m_node.h>
#include <gwenhywfar/debug.h>
@@ -54,6 +55,7 @@ void AQH_NodeServer_HandleForward(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSA
AQH_Message_SetData(nodeMsg, ptr, len);
AQH_Message_SetUsedSize(nodeMsg, len);
AQH_Endpoint_AddMsgOut(xo->ttyEndpoint, nodeMsg);
DBG_ERROR(NULL, "Forwarding node message %d to node", AQH_NodeMessage_GetMsgType(nodeMsg));
}
else {
DBG_ERROR(NULL, "TTY endpoint currently not connected");

View File

@@ -273,7 +273,7 @@ AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_NODE_SERVER *xo,
AQH_MsgRequest_SetRequestMsgId(rq, msgId);
AQH_MsgRequest_SetTimestamps(rq, R_SETDATA_SUBREQUEST_EXPIRE_SECS);
msgOut=AQH_ValueMessage_new(xo->nodeAddress, destAddr, AQH_MSG_TYPE_VALUE_SET, msgId, valueId, dataVal, dataDenom);
msgOut=AQH_ValueMessage_new(destAddr, xo->nodeAddress, AQH_MSG_TYPE_VALUE_SET, msgId, valueId, dataVal, dataDenom);
AQH_Endpoint_AddMsgOut(xo->ttyEndpoint, msgOut);
return rq;

View File

@@ -24,7 +24,7 @@
#include <aqhome/ipc2/ipc_server.h>
#include <aqhome/ipc2/tcpd_object.h>
#include <aqhome/ipc2/tty_endpoint.h>
#include <aqhome/ipc2/ttyobject.h>
#include <aqhome/ipc2/tty_object.h>
#include <aqhome/ipc2/tcp_object.h>
#include <aqhome/ipc2/tcpd_object.h>
#include <aqhome/ipc2/ipc_client.h>
@@ -178,6 +178,9 @@ void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
AQH_Object_free(xo->ipcEndpoint);
AQH_Object_free(xo->ttyEndpoint);
AQH_Object_free(xo->brokerEndpoint);
AQHNODE_Device_List_free(xo->deviceDefList);
GWEN_DB_Group_free(xo->dbArgs);
AQH_MsgRequest_free(xo->requestTree);
AQH_NodeDb_free(xo->nodeDb);
free(xo->dbFile);
@@ -445,6 +448,7 @@ void _readConfig(AQH_OBJECT *o, AQH_NODE_SERVER *xo, GWEN_DB_NODE *dbArgs)
xo->dbArgs=dbArgs;
xo->timeout=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 0);
xo->noAttn=GWEN_DB_GetIntValue(dbArgs, "noAttn", 0, 0);
xo->nodeAddress=GWEN_DB_GetIntValue(dbArgs, "nodeAddress", 0, AQHOMED_DEFAULT_NODEADDR);
AQH_NodeServer_SetDbFile(o, GWEN_DB_GetCharValue(dbArgs, "dbfile", 0, NULL));
@@ -534,7 +538,7 @@ int _startTty(AQH_OBJECT *o, AQH_NODE_SERVER *xo)
DBG_INFO(NULL, "here");
return GWEN_ERROR_IO;
}
xo->ttyEndpoint=AQH_TtyEndpoint2_new(AQH_Object_GetEventLoop(o), fd);
xo->ttyEndpoint=AQH_TtyEndpoint2_new(AQH_Object_GetEventLoop(o), fd, xo->noAttn);
AQH_Object_AddLink(xo->ttyEndpoint, AQH_ENDPOINT_SIGNAL_CLOSED, AQH_NODE_SERVER_SLOT_TTYCLOSED, o);
AQH_Object_Enable(xo->ttyEndpoint);
}
@@ -580,7 +584,7 @@ int _startBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo)
DBG_ERROR(NULL, "Error connecting to broker: %d", rv);
return (rv<0)?rv:GWEN_ERROR_PERMISSIONS;
}
DBG_ERROR(NULL, "Connected to broker at %s:%d", xo->brokerAddress, xo->brokerPort);
DBG_ERROR(NULL, "Fully connected to broker at %s:%d", xo->brokerAddress, xo->brokerPort);
return 0;
}
else {
@@ -793,6 +797,7 @@ void AQH_NodeServer_HandleTtyMsgs(AQH_OBJECT *o)
AQH_MESSAGE *msg;
while( (msg=AQH_Endpoint_GetNextMsgIn(xo->ttyEndpoint)) ) {
_writeTtyMsgToLogFile(xo, msg);
AQH_Message_SetObject(msg, xo->ttyEndpoint);
if (AQH_Request_Tree2_HandleTtyMsg(xo->requestTree, xo->ttyEndpoint, msg)!=AQH_MSG_REQUEST_RESULT_HANDLED)
_handleMsgFromTty(o, xo, msg);
@@ -808,9 +813,8 @@ void _handleMsgFromTty(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAGE *ms
uint8_t code;
code=AQH_NodeMessage_GetMsgType(msg);
DBG_ERROR(NULL, "Received Node packet %d (%x)", (int) code, code);
DBG_INFO(NULL, "Received Node packet %d (%x)", (int) code, code);
AQH_NodeServer_NodeMsgToDb(o, msg);
_writeTtyMsgToLogFile(xo, msg);
_forwardTtyMsgToBroker(o, xo, msg);
_forwardTtyMsgToClients(xo, msg);
}
@@ -979,12 +983,12 @@ void _publishDouble(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vM
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0,
value, arrayToSend, 1);
if (pubMsg) {
DBG_ERROR(AQH_LOGDOMAIN,
"BROKER PUBLISH %s(%s/%s): %f",
AQH_Value_GetName(value),
AQH_Value_GetDeviceName(value),
AQH_Value_GetName(value),
v);
DBG_INFO(AQH_LOGDOMAIN,
"BROKER PUBLISH %s(%s/%s): %f",
AQH_Value_GetName(value),
AQH_Value_GetDeviceName(value),
AQH_Value_GetName(value),
v);
AQH_Endpoint_AddMsgOut(xo->brokerEndpoint, pubMsg);
}
}
@@ -1117,7 +1121,7 @@ void _handleMsgFromBroker(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg)
code=AQH_IpcMessage_GetCode(msg);
protoId=AQH_IpcMessage_GetProtoId(msg);
if (protoId==AQH_IPC_PROTOCOL_DATA_ID) {
DBG_ERROR(NULL, "Received IPC packet %d (%x)", (int) code, code);
DBG_INFO(NULL, "Received IPC packet %d (%x)", (int) code, code);
switch(code) {
case AQH_MSGTYPE_IPC_DATA_SETDATA: AQH_NodeServer_HandleSetData(o, ep, msg); break;
default: break;
@@ -1410,6 +1414,7 @@ int _readArgs(int argc, char **argv, GWEN_DB_NODE *dbArgs)
{ A_ARG, A_CHAR, "dbfile", 0, 1, "db", "dbfile", I18S("DB file to read/write node database"), NULL},
{ A_ARG, A_CHAR, "pidfile", 0, 1, "p", "pidfile", I18S("PID file"), NULL},
{ A_ARG, A_INT, "timeout", 0, 1, "T", NULL, I18S("timeout in seconds [0]"), NULL},
{ 0, A_INT, "noAttn", 0, 1, "N", "noattn", I18S("Don't use ATTN line (for T03 or newer)"), NULL},
{ A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL}
};

View File

@@ -34,6 +34,18 @@
#define AQH_ENDPOINT_VID_STATS_PACKETS_IN 0xe0
#define AQH_ENDPOINT_VID_STATS_PACKETS_OUT 0xe1
#define AQH_ENDPOINT_VID_STATS_ERRS_CONTENT 0xe2
#define AQH_ENDPOINT_VID_STATS_ERRS_IO 0xe3
#define AQH_ENDPOINT_VID_STATS_ERRS_NOBUF 0xe4
#define AQH_ENDPOINT_VID_STATS_ERRS_COLLISIONS 0xe5
#define AQH_ENDPOINT_VID_STATS_ERRS_BUSY 0xe6
#define AQH_ENDPOINT_VID_STATS_HEAP_USED 0xe7
#define AQH_ENDPOINT_VID_STATS_HEAP_FREE 0xe8
AQH_OBJECT *AQH_NodeServer_new(AQH_EVENT_LOOP *eventLoop);
int AQH_NodeServer_Init(AQH_OBJECT *o, int argc, char **argv);
void AQH_NodeServer_Fini(AQH_OBJECT *o);

View File

@@ -70,6 +70,7 @@ struct AQH_NODE_SERVER {
uint8_t protoId;
uint8_t protoVer;
int noAttn;
};

View File

@@ -103,6 +103,7 @@
<headers dist="true" >
server.h
server_p.h
net_read.h
suntimes.h
</headers>

View File

@@ -14,13 +14,13 @@
#include "./net_read.h"
#include "aqhome-react/units/u_timer.h"
#include "aqhome-react/types/prgrule.h"
//#include "aqhome-react/types/prgrule-t.h"
#include "aqhome-react/types/prgrule-t.h"
#include "aqhome/aqhome.h"
#include "aqhome/data/path-t.h"
#include "aqhome/data/vars-t.h"
//#include "aqhome/data/vars_dbread-t.h"
//#include "aqhome/data/vars_dbwrite-t.h"
#include "aqhome/data/vars_dbread-t.h"
#include "aqhome/data/vars_dbwrite-t.h"
#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/args.h>
@@ -69,7 +69,8 @@
static void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop);
static int _diffInSeconds(time_t t1, time_t t0);
//static int _testModules(int argc, char **argv);
static int _testModules(int argc, char **argv);
static int _test(int argc, char **argv);
#ifdef HAVE_SIGNAL_H
static int _setSignalHandlers(void);
@@ -126,6 +127,26 @@ int main(int argc, char **argv)
gui=GWEN_Gui_CGui_new();
GWEN_Gui_SetGui(gui);
if (argc>1) {
const char *cmd;
cmd=argv[1];
if (cmd && *cmd) {
if (strcasecmp(cmd, "unittest")==0) {
rv=_testModules(argc, argv);
GWEN_Gui_SetGui(NULL);
GWEN_Gui_free(gui);
return rv;
}
else if (strcasecmp(cmd, "test")==0) {
rv=_test(argc, argv);
GWEN_Gui_SetGui(NULL);
GWEN_Gui_free(gui);
return rv;
}
}
}
eventLoop=AQH_EventLoop_new();
aqh=AQH_ReactServer_new(eventLoop);
rv=AQH_ReactServer_Init(aqh, argc, argv);
@@ -140,6 +161,7 @@ int main(int argc, char **argv)
AQH_ReactServer_Fini(aqh);
AQH_Object_free(aqh);
AQH_EventLoop_free(eventLoop);
GWEN_Gui_SetGui(NULL);
GWEN_Gui_free(gui);
@@ -198,7 +220,7 @@ void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop)
}
if (_diffInSeconds(now, lastSaveTime)>AQHOME_REACT_SAVE_INTERVAL) {
DBG_ERROR(NULL, "Writing var file");
DBG_INFO(NULL, "Writing var file");
rv=AQH_ReactServer_WriteVarsFile(aqh);
if (rv<0) {
DBG_INFO(NULL, "Error writing runtime data");
@@ -287,7 +309,7 @@ void _signalHandler(int s)
}
#if 0
int _testModules(int argc, char **argv)
{
GWEN_GUI *gui;
@@ -344,7 +366,29 @@ int _testModules(int argc, char **argv)
GWEN_Gui_free(gui);
return 0;
}
#endif
int _test(int argc, char **argv)
{
if (argc>2) {
AQHREACT_PRGRULE_LIST *ruleList;
GWEN_Logger_SetLevel(0, GWEN_LoggerLevel_Info);
ruleList=AQHREACT_PrgRule_ReadRules(argv[2]);
if (ruleList==NULL) {
DBG_ERROR(NULL, "Error in rules");
return 2;
}
DBG_ERROR(NULL, "Rules ok (%d)", AQHREACT_PrgRule_List_GetCount(ruleList));
AQHREACT_PrgRule_List_free(ruleList);
return 0;
}
else {
DBG_ERROR(NULL, "No rules");
return 2;
}
}

View File

@@ -12,7 +12,6 @@
#include "./net_read.h"
#include "./server_p.h"
#include "aqhome-react/aqhome_react_p.h"
#include "aqhome-react/types/unit.h"
#include "aqhome-react/units/u_module.h"

View File

@@ -10,7 +10,7 @@
#define AQHOMEREACT_NET_READ_H
#include "./aqhome_react.h"
#include "./server.h"
int AQH_ReactServer_ReadUnitNetFiles(AQH_OBJECT *aqh);

View File

@@ -150,7 +150,13 @@ void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
xo=(AQH_REACT_SERVER*) p;
AQH_Object_free(xo->brokerEndpoint);
GWEN_DB_Group_free(xo->dbArgs);
free(xo->pidFile);
free(xo->varsFile);
free(xo->brokerAddress);
free(xo->brokerClientId);
AQHREACT_Unit_List_free(xo->unitList);
AQH_Vars_free(xo->localVars);
GWEN_FREE_OBJECT(xo);
}
@@ -496,7 +502,7 @@ int _startBroker(AQH_OBJECT *o, AQH_REACT_SERVER *xo)
DBG_ERROR(NULL, "Error connecting to broker: %d", rv);
return (rv<0)?rv:GWEN_ERROR_PERMISSIONS;
}
DBG_INFO(NULL, "Connected to broker at %s:%d", xo->brokerAddress, xo->brokerPort);
DBG_ERROR(NULL, "Fully connected to broker at %s:%d", xo->brokerAddress, xo->brokerPort);
return 0;
}
else {

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -11,6 +11,7 @@
#include <gwenhywfar/list.h>
#include <gwenhywfar/buffer.h>
typedef struct AQHREACT_DATAOBJECT AQHREACT_DATAOBJECT;
@@ -25,7 +26,7 @@ enum {
};
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/server.h"

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -20,6 +20,9 @@ GWEN_LIST_FUNCTION_DEFS(AQHREACT_LINK, AQHREACT_Link)
#include "aqhome-react/types/unit.h"
#include "aqhome-react/types/port.h"
#include <gwenhywfar/buffer.h>
AQHREACT_LINK *AQHREACT_Link_new();
void AQHREACT_Link_free(AQHREACT_LINK *lnk);

View File

@@ -16,7 +16,7 @@
typedef struct AQHREACT_PARAM AQHREACT_PARAM;
GWEN_LIST_FUNCTION_DEFS(AQHREACT_PARAM, AQHREACT_Param)
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/server.h"

View File

@@ -16,10 +16,11 @@ typedef struct AQHREACT_PORT AQHREACT_PORT;
GWEN_LIST_FUNCTION_DEFS(AQHREACT_PORT, AQHREACT_Port)
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/link.h"
#include "aqhome-react/types/dataobject.h"
#include <gwenhywfar/buffer.h>
AQHREACT_PORT *AQHREACT_Port_new();

View File

@@ -349,7 +349,7 @@ const char *_readDouble(const char *s, double *ptrDouble)
while(*s && isspace(*s))
s++;
sStart=s;
while(*s && (isdigit(*s) || *s=='.'))
while(*s && (isdigit(*s) || *s=='.' || *s=='+' || *s=='-'))
s++;
rv=GWEN_Text_StringToDouble(sStart, ptrDouble);
@@ -419,7 +419,7 @@ void _setBitField(uint64_t *ptrBitField, int startValue, int endValue)
//#include "prgrule-t.c"
#include "prgrule-t.c"

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -10,7 +10,7 @@
#define AQHOME_REACT_PRGRULE_H
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/server.h"
#include <gwenhywfar/gwentime.h>
#include <gwenhywfar/list.h>

View File

@@ -46,6 +46,7 @@ void AQHREACT_Unit_free(AQHREACT_UNIT *unit)
GWEN_INHERIT_FINI(AQHREACT_UNIT, unit);
free(unit->typeName);
free(unit->description);
free(unit->id);
AQHREACT_Port_List_free(unit->outputPortList);
AQHREACT_Port_List_free(unit->inputPortList);
AQHREACT_Param_List_free(unit->paramList);
@@ -490,7 +491,7 @@ void AQHREACT_Unit_OutputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQ
void AQHREACT_Unit_OutputDoubleData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, double data)
{
if (unit && unit->outputPortList) {
if (unit && port && unit->outputPortList) {
AQHREACT_DATAOBJECT *dataObject;
dataObject=AQHREACT_DataObject_new();
@@ -505,7 +506,7 @@ void AQHREACT_Unit_OutputDoubleData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, do
void AQHREACT_Unit_OutputStringData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const char *data)
{
if (unit && unit->outputPortList) {
if (unit && port && unit->outputPortList) {
AQHREACT_DATAOBJECT *dataObject;
dataObject=AQHREACT_DataObject_new();

View File

@@ -26,7 +26,6 @@ GWEN_INHERIT_FUNCTION_DEFS(AQHREACT_UNIT)
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/port.h"
#include "aqhome-react/types/param.h"
#include "aqhome-react/types/dataobject.h"

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"
#include <gwenhywfar/xml.h>

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -12,7 +12,6 @@
#include "./u_module.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"
#include <gwenhywfar/list.h>

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -14,6 +14,8 @@
#include <gwenhywfar/debug.h>
#include <time.h>
/* ------------------------------------------------------------------------------------------------

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"
#define AQHOMEREACT_UNIT_STABILIZE_PARAM_HOLDTIME_HIGH "holdTimeHigh"

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -246,8 +246,12 @@ int _hasDateChanged(AQHREACT_UNIT *unit)
GWEN_DATE *today;
today=GWEN_Date_CurrentDate();
if (GWEN_Date_Compare(today, xunit->date)!=0)
if (GWEN_Date_Compare(today, xunit->date)!=0) {
GWEN_Date_free(today);
return 1;
}
GWEN_Date_free(today);
}
}

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -12,7 +12,6 @@
#include "./u_suntime.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"
#include <gwenhywfar/gwentime.h>

View File

@@ -29,6 +29,10 @@
#define AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT 0
#define AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEFORNEXT_MINS 60 /* 1h */
#define AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEEVERY_SECS (15*60) /* 15m */
#define AQHOMEREACT_UNIT_TIMEPROGRAM_CHECKINTERVAL_SEC 60 /* 1m */
GWEN_INHERIT(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM);
@@ -39,19 +43,17 @@ GWEN_INHERIT(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM);
* ------------------------------------------------------------------------------------------------
*/
static MODULE_TIMER_ACTION *ModuleTimerAction_new(int hourTime, double value);
static MODULE_TIMER_ACTION *ModuleTimerAction_new(int64_t triggerTime, double value);
static void ModuleTimerAction_free(MODULE_TIMER_ACTION *act);
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
static int _cbProcess(AQHREACT_UNIT *unit);
static int _readRules(AQHREACT_UNIT *unit);
static int _handleActionsForGivenTime(AQHREACT_UNIT *unit, int hourMins);
static int _checkAndAddActions(AQHREACT_UNIT *unit);
static int _addActionsForGivenTime(const GWEN_TIME *ti,
int hour,
const AQHREACT_PRGRULE_LIST *ruleList,
MODULE_TIMER_ACTION_LIST *actionList);
static int _checkAndAddActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit);
static int _addActionsForNextMinutes(AQHREACT_UNIT_TIMEPROGRAM *xunit, int minutes,
const AQHREACT_PRGRULE_LIST *ruleList, MODULE_TIMER_ACTION_LIST *actionList);
static int _handlePendingActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit);
@@ -68,14 +70,14 @@ GWEN_LIST_FUNCTIONS(MODULE_TIMER_ACTION, ModuleTimerAction);
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
MODULE_TIMER_ACTION *ModuleTimerAction_new(int hourTime, double value)
MODULE_TIMER_ACTION *ModuleTimerAction_new(int64_t triggerTime, double value)
{
MODULE_TIMER_ACTION *act;
GWEN_NEW_OBJECT(MODULE_TIMER_ACTION, act);
GWEN_LIST_INIT(MODULE_TIMER_ACTION, act);
act->hourMinutes=hourTime;
act->triggerTime=triggerTime;
act->value=value;
return act;
@@ -112,6 +114,7 @@ AQHREACT_UNIT *AqHomeReact_UnitTimeProgram_new(AQH_OBJECT *aqh)
GWEN_INHERIT_SETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit, xunit, _freeData);
xunit->actionList=ModuleTimerAction_List_new();
xunit->lastActionHour=-1;
AQHREACT_Unit_SetProcessFn(unit, _cbProcess);
port=AQHREACT_Port_new();
@@ -125,6 +128,8 @@ AQHREACT_UNIT *AqHomeReact_UnitTimeProgram_new(AQH_OBJECT *aqh)
AQHREACT_Param_SetDataType(param, AQHREACT_DATAOBJECTTYPE_STRING);
AQHREACT_Unit_AddParam(unit, param);
xunit->nextAddTime=GWEN_Timestamp_NowInLocalTime();
return unit;
}
@@ -138,6 +143,7 @@ void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
ModuleTimerAction_List_free(xunit->actionList);
AQHREACT_PrgRule_List_free(xunit->ruleList);
GWEN_Timestamp_free(xunit->nextAddTime);
GWEN_FREE_OBJECT(xunit);
}
@@ -155,6 +161,7 @@ int _cbProcess(AQHREACT_UNIT *unit)
int rv;
if (xunit->ruleList==NULL) {
DBG_INFO(NULL, "Reading rules");
rv=_readRules(unit);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
@@ -163,7 +170,7 @@ int _cbProcess(AQHREACT_UNIT *unit)
didSomething=1;
}
rv=_checkAndAddActions(unit);
rv=_checkAndAddActions(unit, xunit);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
@@ -177,58 +184,40 @@ int _cbProcess(AQHREACT_UNIT *unit)
int _checkAndAddActions(AQHREACT_UNIT *unit)
int _checkAndAddActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit)
{
AQHREACT_UNIT_TIMEPROGRAM *xunit;
GWEN_TIME *ti;
int didSomething=0;
xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit);
ti=GWEN_CurrentTime();
if (ti) {
int hours;
int mins;
int secs;
int hourMins;
if (xunit) {
time_t now;
int rv;
/* translate current time */
rv=GWEN_Time_GetBrokenDownTime(ti, &hours, &mins, &secs);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
GWEN_Time_free(ti);
return rv;
}
hourMins=(hours*60)+mins;
rv=GWEN_Time_AddSeconds(ti, 60*60); /* next hour */
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
GWEN_Time_free(ti);
return rv;
now=time(NULL);
if ((now-xunit->lastCreateTime)>AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEEVERY_SECS) {
rv=_addActionsForNextMinutes(xunit,
AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEFORNEXT_MINS,
xunit->ruleList,
xunit->actionList);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
if (rv>0)
didSomething=1;
xunit->lastCreateTime=now;
}
rv=GWEN_Time_GetBrokenDownTime(ti, &hours, &mins, &secs);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
GWEN_Time_free(ti);
return rv;
if ((now-xunit->lastCheckTime)>AQHOMEREACT_UNIT_TIMEPROGRAM_CHECKINTERVAL_SEC) {
rv=_handlePendingActions(unit, xunit);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
if (rv>0)
didSomething=1;
xunit->lastCheckTime=now;
}
if (hours!=xunit->lastActionHour) {
DBG_INFO(NULL, "Adding actions for next hour %02d", hours);
_addActionsForGivenTime(ti, hours, xunit->ruleList, xunit->actionList);
xunit->lastActionHour=hours;
didSomething=1;
}
GWEN_Time_free(ti);
rv=_handleActionsForGivenTime(unit, hourMins);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
if (rv>0)
didSomething=1;
}
return didSomething?1:0;
@@ -236,64 +225,86 @@ int _checkAndAddActions(AQHREACT_UNIT *unit)
int _handleActionsForGivenTime(AQHREACT_UNIT *unit, int hourMins)
int _handlePendingActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit)
{
AQHREACT_UNIT_TIMEPROGRAM *xunit;
MODULE_TIMER_ACTION *action;
int valueSent=0;
xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit);
action=ModuleTimerAction_List_First(xunit->actionList);
while(action) {
MODULE_TIMER_ACTION *nextAction;
if (unit && xunit) {
AQHREACT_PORT *outputPort;
nextAction=ModuleTimerAction_List_Next(action);
if ((hourMins>action->hourMinutes) || (hourMins+(23*60))<action->hourMinutes) {
ModuleTimerAction_List_Del(action);
DBG_INFO(NULL, "Sending output value %.2f", action->value);
AQHREACT_Unit_OutputDoubleData(unit, AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT, action->value);
ModuleTimerAction_free(action);
valueSent=1;
outputPort=AQHREACT_Unit_GetOutputPortByIdForUnit(unit, AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT);
if (outputPort) {
GWEN_TIMESTAMP *ts;
int64_t nowInt64;
MODULE_TIMER_ACTION *action;
ts=GWEN_Timestamp_NowInLocalTime();
nowInt64=ts?GWEN_Timestamp_toInt64(ts):0;
GWEN_Timestamp_free(ts);
xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit);
action=ModuleTimerAction_List_First(xunit->actionList);
while(action) {
MODULE_TIMER_ACTION *nextAction;
nextAction=ModuleTimerAction_List_Next(action);
if (action->triggerTime<nowInt64) {
ModuleTimerAction_List_Del(action);
DBG_ERROR(NULL, "Sending output value %.2f", action->value);
AQHREACT_Unit_OutputDoubleData(unit, outputPort, action->value);
ModuleTimerAction_free(action);
valueSent=1;
}
action=nextAction;
}
}
action=nextAction;
}
return valueSent?1:0;
}
int _addActionsForGivenTime(const GWEN_TIME *ti, int hour, const AQHREACT_PRGRULE_LIST *ruleList, MODULE_TIMER_ACTION_LIST *actionList)
int _addActionsForNextMinutes(AQHREACT_UNIT_TIMEPROGRAM *xunit,
int minutes,
const AQHREACT_PRGRULE_LIST *ruleList,
MODULE_TIMER_ACTION_LIST *actionList)
{
int actionsAdded=0;
GWEN_DATE *dt;
int dayOfMonth;
int month;
int dayOfWeek;
int mins;
int i;
GWEN_TIMESTAMP *tsWork;
dt=GWEN_Date_fromTime(ti);
month=GWEN_Date_GetMonth(dt);
dayOfMonth=GWEN_Date_GetDay(dt);
dayOfWeek=GWEN_Date_WeekDay(dt);
GWEN_Date_free(dt);
tsWork=GWEN_Timestamp_NowInLocalTime();
for (i=0; i<minutes; i++) {
if (GWEN_Timestamp_Compare(tsWork, xunit->nextAddTime)==1) {
int64_t triggerTime;
const AQHREACT_PRGRULE *rule;
for (mins=0; mins<60; mins++) {
const AQHREACT_PRGRULE *rule;
triggerTime=GWEN_Timestamp_toInt64(tsWork);
rule=AQHREACT_PrgRule_List_First(ruleList);
while(rule) {
if (AQHREACT_PrgRule_Matches(rule, mins, hour, dayOfMonth, month, dayOfWeek)>0) {
MODULE_TIMER_ACTION *act;
rule=AQHREACT_PrgRule_List_First(ruleList);
while(rule) {
if (AQHREACT_PrgRule_Matches(rule,
GWEN_Timestamp_GetMinute(tsWork),
GWEN_Timestamp_GetHour(tsWork),
GWEN_Timestamp_GetDay(tsWork),
GWEN_Timestamp_GetMonth(tsWork),
GWEN_Timestamp_GetWeekDay(tsWork))>0) {
MODULE_TIMER_ACTION *act;
act=ModuleTimerAction_new((hour*60)+mins, AQHREACT_PrgRule_GetValue(rule));
ModuleTimerAction_List_Add(act, actionList);
actionsAdded=1;
}
rule=AQHREACT_PrgRule_List_Next(rule);
DBG_ERROR(NULL, "- rule matches for %s, creating action", GWEN_Timestamp_GetString(tsWork));
act=ModuleTimerAction_new(triggerTime, AQHREACT_PrgRule_GetValue(rule));
ModuleTimerAction_List_Add(act, actionList);
actionsAdded=1;
}
rule=AQHREACT_PrgRule_List_Next(rule);
} /* while */
}
}
GWEN_Timestamp_AddSeconds(tsWork, 60); /* next min */
} /* for */
GWEN_Timestamp_free(xunit->nextAddTime);
xunit->nextAddTime=tsWork;
return actionsAdded?1:0;
}

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -12,11 +12,14 @@
#include "./u_timeprogram.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"
#include "aqhome-react/types/prgrule.h"
#include <gwenhywfar/list.h>
#include <gwenhywfar/timestamp.h>
#include <time.h>
@@ -30,7 +33,7 @@ GWEN_LIST_FUNCTION_DEFS(MODULE_TIMER_ACTION, ModuleTimerAction)
struct MODULE_TIMER_ACTION {
GWEN_LIST_ELEMENT(MODULE_TIMER_ACTION)
int hourMinutes;
int64_t triggerTime;
double value;
};
@@ -41,6 +44,10 @@ struct AQHREACT_UNIT_TIMEPROGRAM {
MODULE_TIMER_ACTION_LIST *actionList;
int lastActionHour;
GWEN_TIMESTAMP *nextAddTime;
time_t lastCheckTime;
time_t lastCreateTime;
};

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -96,7 +96,7 @@ void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAO
msgOut=_mkSetDataMsgString(brokerEndpoint, sValueName, dataObject);
break;
default:
DBG_INFO(NULL, "Unhandled data type (%d)", AQHREACT_DataObject_GetDataType(dataObject));
DBG_ERROR(NULL, "Unhandled data type (%d)", AQHREACT_DataObject_GetDataType(dataObject));
msgOut=NULL;
break;
}
@@ -111,7 +111,15 @@ void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAO
GWEN_Buffer_free(dbuf);
AQH_Message_free(msgOut);
#else
DBG_INFO(NULL, "Sending data for value \"%s\"", sValueName);
GWEN_BUFFER *dbuf;
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendArgs(dbuf, "Send: \"%s\" = ", sValueName);
AQHREACT_DataObject_Dump(dataObject, dbuf, 0);
DBG_ERROR(NULL, "%s\n", GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_free(dbuf);
// DBG_ERROR(NULL, "Sending data for value \"%s\"", sValueName);
AQH_Endpoint_AddMsgOut(brokerEndpoint, msgOut);
#endif
}

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"
#include "aqhome/data/value.h"

View File

@@ -12,14 +12,14 @@
#include "./u_varset.h"
#include "aqhome/ipc/data/msg_data_set.h"
#include "aqhome/ipc/data/ipc_data.h"
#include "aqhome/msg/ipc/data/m_ipcd_setdata.h"
#include "aqhome/msg/ipc/data/m_ipcd.h"
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>
#define DEBUG_DRY_RUN 1 /* don't actually set value if "1" */
#define DEBUG_DRY_RUN 0 /* don't actually set value if "1" */
/* ------------------------------------------------------------------------------------------------

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -103,7 +103,7 @@ void _cbInputData(AQHREACT_UNIT *unit, GWEN_UNUSED AQHREACT_PORT *port, const AQ
result=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUE_ZERO, NULL);
if (result && *result) {
DBG_DEBUG(NULL, "Sending \"%s\" to output", result);
DBG_INFO(NULL, "Sending \"%s\" to output", result);
AQHREACT_Unit_OutputStringData(unit, outputPort, result);
}
}

View File

@@ -11,7 +11,6 @@
#include "aqhome-react/server.h"
#include "aqhome-react/aqhome_react.h"
#include "aqhome-react/types/unit.h"

View File

@@ -493,7 +493,7 @@ AQH_MESSAGE *AQH_ToolClient_WaitForNodeMsg(AQH_OBJECT *o, int nodeSrcAddr, uint8
}
}
else {
DBG_INFO(NULL, "Received unexpected message %d (%x), ignoring", code, code);
DBG_DEBUG(NULL, "Received unexpected message %d (%x), ignoring", code, code);
}
GWEN_Tag16_List_free(tagList);
}
@@ -525,9 +525,9 @@ int AQH_ToolClient_HandleResultMsg(GWEN_UNUSED const AQH_MESSAGE *msg, const GWE
text=AQH_IpcMessageResult_GetText(tagList);
DBG_ERROR(NULL, "ERROR: %d (%s)", result, text?text:"");
return 3;
return GWEN_ERROR_GENERIC;
}
return 0;
return 1;
}

View File

@@ -37,6 +37,9 @@
getdevices.h
adddata.h
getdatapoints.h
getfirstdata.h
getlastdata.h
getperioddata.h
setdata.h
moddevice.h
watch.h
@@ -49,6 +52,9 @@
getdevices.c
adddata.c
getdatapoints.c
getfirstdata.c
getlastdata.c
getperioddata.c
setdata.c
moddevice.c
watch.c

View File

@@ -80,6 +80,7 @@ int AQH_Tool_AddDataPoint(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
eventLoop=AQH_EventLoop_new();
o=AQH_ToolClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, dbGlobalArgs, args);
AQH_ToolClient_AddFlags(o, AQH_TOOL_CLIENT_CONNECTFLAGS_WITHCONNECTMSG);
AQH_ToolClient_SetCreateRequestMessageFn(o, _createRequestMessage);
rv=AQH_ToolClient_ReadLocalArgs(o, argc, argv);
if (rv!=0)

View File

@@ -10,7 +10,7 @@
# include <config.h>
#endif
#include "./getvalues.h"
#include "./getdatapoints.h"
#include "../client.h"
#include "../utils.h"
@@ -52,7 +52,6 @@
static AQH_MESSAGE *_createRequestMessage(AQH_OBJECT *o, uint32_t msgId);
static int _handleResponseMessage(AQH_OBJECT *o, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList, int first);
static void _handleDataResponse(const GWEN_TAG16_LIST *tagList, int printMean, int printDiff);
static uint64_t _getTimeStampFromString(const char *s);
@@ -85,6 +84,7 @@ int AQH_Tool_GetDataPoints(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
eventLoop=AQH_EventLoop_new();
o=AQH_ToolClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, dbGlobalArgs, args);
AQH_ToolClient_AddFlags(o, AQH_TOOL_CLIENT_CONNECTFLAGS_WITHCONNECTMSG);
AQH_ToolClient_SetCreateRequestMessageFn(o, _createRequestMessage);
AQH_ToolClient_SetHandleResponseMessageFn(o, _handleResponseMessage);
rv=AQH_ToolClient_ReadLocalArgs(o, argc, argv);
@@ -109,18 +109,23 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId)
dbArgs=AQH_ToolClient_GetDbLocalArgs(o);
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
num=GWEN_DB_GetIntValue(dbArgs, "numOfLastDatapoints", 0, 0);
tsBegin=_getTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsBegin", 0, NULL));
tsBegin=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsBegin", 0, NULL));
if (tsBegin==(uint64_t) (-1)) {
DBG_ERROR(NULL, "Bad begin timestamp");
return NULL;
}
tsEnd=_getTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsEnd", 0, NULL));
tsEnd=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsEnd", 0, NULL));
if (tsEnd==(uint64_t) (-1)) {
DBG_ERROR(NULL, "Bad end timestamp");
return NULL;
}
return AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ, msgId, 0, valueName, tsBegin, tsEnd, num);
// TODO: use "mode" correctly
return AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ,
msgId, 0,
AQH_MSGDATA_GETDATA_MODE_LAST,
valueName,
tsBegin, tsEnd, num);
}
@@ -177,45 +182,3 @@ void _handleDataResponse(const GWEN_TAG16_LIST *tagList, int printMean, int prin
uint64_t _getTimeStampFromString(const char *s)
{
if (s && *s) {
if (*s=='-') {
uint64_t x=0;
uint64_t now=time(NULL);
s++;
while(*s && isdigit(*s)) {
unsigned int i;
i=*(s++)-'0';
x*=10;
x+=i;
}
if (*s) {
switch(*s) {
case 0:
case 'm': x*=60; break;
case 'h': x*=(60*60); break;
case 'd': x*=(60*60*24); break;
default: break;
}
}
return (now-x);
}
else {
unsigned long int x;
if (1!=sscanf(s, "%lu", &x)) {
DBG_ERROR(NULL, "ERROR: Invalid timestamp");
return (uint64_t) (-1);
}
return (uint64_t) x;
}
}
return 0;
}

View File

@@ -75,6 +75,7 @@ int AQH_Tool_GetDevices(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
eventLoop=AQH_EventLoop_new();
o=AQH_ToolClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, dbGlobalArgs, args);
AQH_ToolClient_AddFlags(o, AQH_TOOL_CLIENT_CONNECTFLAGS_WITHCONNECTMSG);
AQH_ToolClient_SetCreateRequestMessageFn(o, _createRequestMessage);
AQH_ToolClient_SetHandleResponseMessageFn(o, _handleResponseMessage);
rv=AQH_ToolClient_ReadLocalArgs(o, argc, argv);

View File

@@ -0,0 +1,153 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./getfirstdata.h"
#include "../utils.h"
#include "aqhome/dataclient/client.h"
#include "aqhome/msg/ipc/m_ipc.h"
#include "aqhome/msg/ipc/m_ipc_result.h"
#include "aqhome/msg/ipc/data/m_ipcd.h"
#include "aqhome/msg/ipc/data/m_ipcd_getdata.h"
#include "aqhome/msg/ipc/data/m_ipcd_multidata.h"
#include "aqhome/dataclient/client.h"
#include <gwenhywfar/args.h>
#include <gwenhywfar/i18n.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>
#include <ctype.h>
/* ------------------------------------------------------------------------------------------------
* defs
* ------------------------------------------------------------------------------------------------
*/
#define I18S(msg) msg
#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
#define A_ARG GWEN_ARGS_FLAGS_HAS_ARGUMENT
#define A_END (GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST)
#define A_CHAR GWEN_ArgsType_Char
#define A_INT GWEN_ArgsType_Int
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static int _runCommand(AQH_DATACLIENT *dc);
/* ------------------------------------------------------------------------------------------------
* code
* ------------------------------------------------------------------------------------------------
*/
int AQH_Tool_GetFirstData(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
{
AQH_EVENT_LOOP *eventLoop;
AQH_DATACLIENT *dc;
int rv;
const GWEN_ARGS args[]= {
/* flags type name min max s long short_descr, long_descr */
{ A_ARG, A_CHAR, "brokerAddress", 0, 1, "t", "tcpaddress", I18S("TCP address to connect to [127.0.0.1]"), NULL},
{ A_ARG, A_INT, "brokerPort", 0, 1, "P", "tcpport", I18S("Specify the TCP port to listen on"), NULL},
{ A_ARG, A_INT, "timeout", 0, 1, "T", NULL, I18S("Specify timeout in seconds for response"), NULL},
{ A_ARG, A_CHAR, "brokerClientId", 0, 1, "c", "clientid", I18S("Specify CLIENTID"), NULL},
{ A_ARG, A_CHAR, "userId", 0, 1, "u", "userid", I18S("Specify user id"), NULL},
{ A_ARG, A_CHAR, "password", 0, 1, "p", "password", I18S("Specify service password"), NULL},
{ A_ARG, A_CHAR, "valueName", 1, 1, "N", "valuename", I18S("Value name (e.g. server/temp/system)"), NULL},
{ A_ARG, A_INT, "numOfDatapoints", 0, 1, "n", NULL, I18S("Get up to n datapoints"), NULL},
{ 0, A_INT, "printMean", 0, 1, "M", "mean", I18S("Print mean value of data received"), NULL},
{ 0, A_INT, "printDiff", 0, 1, "D", "diff", I18S("Print diff last-first value"), NULL},
{ A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL}
};
eventLoop=AQH_EventLoop_new();
dc=AQH_DataClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION);
rv=AQH_DataClient_ReadLocalArgs(dc, dbGlobalArgs, args, argc, argv);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
AQH_DataClient_free(dc);
AQH_EventLoop_free(eventLoop);
return 2;
}
rv=AQH_DataClient_ConnectWithArgs(dc, 0);
if (rv<0) {
DBG_ERROR(NULL, "Error connecting (%d)", rv);
AQH_DataClient_free(dc);
AQH_EventLoop_free(eventLoop);
return 2;
}
rv=_runCommand(dc);
if (rv<0) {
DBG_ERROR(NULL, "Error running (%d)", rv);
AQH_DataClient_free(dc);
AQH_EventLoop_free(eventLoop);
return 2;
}
AQH_DataClient_free(dc);
AQH_EventLoop_free(eventLoop);
return 0;
}
int _runCommand(AQH_DATACLIENT *dc)
{
GWEN_DB_NODE *dbLocalArgs;
const char *valueName;
uint64_t num;
int printMean;
int printDiff;
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
valueName=GWEN_DB_GetCharValue(dbLocalArgs, "valueName", 0, NULL);
num=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 1);
printMean=GWEN_DB_GetIntValue(dbLocalArgs, "printMean", 0, 0);
printDiff=GWEN_DB_GetIntValue(dbLocalArgs, "printDiff", 0, 0);
if (num>0) {
uint64_t *dataPoints;
uint64_t recvdNum;
dataPoints=malloc(num*sizeof(uint64_t)*2);
recvdNum=AQH_DataClient_GetFirstData(dc, valueName, dataPoints, num);
if (recvdNum>0) {
if (printMean)
Utils_PrintMeanData(dataPoints, recvdNum, NULL);
else if (printDiff)
Utils_PrintDiffData(dataPoints, recvdNum, NULL);
else
Utils_PrintDataPoints(dataPoints, recvdNum, NULL);
}
free(dataPoints);
}
return 0;
}

View File

@@ -0,0 +1,21 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_TOOL_GETFIRSTDATA_H
#define AQHOME_TOOL_GETFIRSTDATA_H
#include <gwenhywfar/db.h>
int AQH_Tool_GetFirstData(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv);
#endif

Some files were not shown because too many files have changed in this diff Show More