_loraFiles.ino 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. // 1-channel LoRa Gateway for ESP8266
  2. // Copyright (c) 2016, 2017, 2018, 2019 Maarten Westenberg version for ESP8266
  3. // Version 6.1.3
  4. // Date: 2019-11-20
  5. //
  6. // based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
  7. // and many others.
  8. //
  9. // All rights reserved. This program and the accompanying materials
  10. // are made available under the terms of the MIT License
  11. // which accompanies this distribution, and is available at
  12. // https://opensource.org/licenses/mit-license.php
  13. //
  14. // NO WARRANTY OF ANY KIND IS PROVIDED
  15. //
  16. // Author: Maarten Westenberg (mw12554@hotmail.com)
  17. //
  18. // This file contains the LoRa filesystem specific code
  19. // ============================================================================
  20. // LORA SPIFFS FILESYSTEM FUNCTIONS
  21. //
  22. // The LoRa supporting functions are in the section below
  23. // ----------------------------------------------------------------------------
  24. // Supporting function to readConfig
  25. // ----------------------------------------------------------------------------
  26. void id_print (String id, String val) {
  27. #if _DUSB>=1
  28. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  29. Serial.print(id);
  30. Serial.print(F("=\t"));
  31. Serial.println(val);
  32. }
  33. #endif
  34. }
  35. // ----------------------------------------------------------------------------
  36. // INITCONFIG; Init the gateway configuration file
  37. // Espcecially when calling SPIFFS.format() the gateway is left in an init
  38. // which is not very well defined. This function will init some of the settings
  39. // to well known settings.
  40. // ----------------------------------------------------------------------------
  41. int initConfig(struct espGwayConfig *c) {
  42. (*c).ch = 0;
  43. (*c).sf = _SPREADING;
  44. (*c).debug = 1;
  45. (*c).pdebug = P_GUI;
  46. (*c).cad = _CAD;
  47. (*c).hop = false;
  48. (*c).expert = false;
  49. (*c).txDelay = 0; // First Value without saving is 0;
  50. (*c).trusted = 1;
  51. }
  52. // ----------------------------------------------------------------------------
  53. // Read the gateway configuration file
  54. // ----------------------------------------------------------------------------
  55. int readConfig(const char *fn, struct espGwayConfig *c) {
  56. int tries = 0;
  57. #if _DUSB>=1
  58. Serial.println(F("readConfig:: Starting "));
  59. #endif
  60. if (!SPIFFS.exists(fn)) {
  61. #if _DUSB>=1
  62. Serial.print(F("readConfig ERR:: file="));
  63. Serial.print(fn);
  64. Serial.println(F(" does not exist .. Formatting"));
  65. #endif
  66. SPIFFS.format();
  67. initConfig(c); // If we cannot read teh config, at least init known values
  68. return(-1);
  69. }
  70. File f = SPIFFS.open(fn, "r");
  71. if (!f) {
  72. #if _DUSB>=1
  73. Serial.println(F("ERROR:: SPIFFS open failed"));
  74. #endif
  75. return(-1);
  76. }
  77. while (f.available()) {
  78. #if _DUSB>=1
  79. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  80. Serial.print('.');
  81. }
  82. #endif
  83. // If we wait for more than 10 times, reformat the filesystem
  84. // We do this so that the system will be responsive (over OTA for example).
  85. //
  86. if (tries >= 10) {
  87. f.close();
  88. #if _DUSB>=1
  89. if (( debug>=0 ) && ( pdebug & P_MAIN ))
  90. Serial.println(F("Formatting"));
  91. #endif
  92. SPIFFS.format();
  93. initConfig(c);
  94. f = SPIFFS.open(fn, "r");
  95. tries = 0;
  96. }
  97. String id =f.readStringUntil('='); // Read keyword until '=', C++ thing
  98. String val=f.readStringUntil('\n'); // Read value until End of Line (EOL)
  99. #if _DUSB>=2
  100. Serial.print(F("readConfig:: reading line="));
  101. Serial.print(id);
  102. Serial.print(F("="));
  103. Serial.print(val);
  104. Serial.println();
  105. #endif
  106. if (id == "SSID") { // WiFi SSID
  107. id_print(id, val);
  108. (*c).ssid = val; // val contains ssid, we do NO check
  109. }
  110. else if (id == "PASS") { // WiFi Password
  111. id_print(id, val);
  112. (*c).pass = val;
  113. }
  114. else if (id == "CH") { // Frequency Channel
  115. id_print(id,val);
  116. (*c).ch = (uint32_t) val.toInt();
  117. }
  118. else if (id == "SF") { // Spreading Factor
  119. id_print(id, val);
  120. (*c).sf = (uint32_t) val.toInt();
  121. }
  122. else if (id == "FCNT") { // Frame Counter
  123. id_print(id, val);
  124. (*c).fcnt = (uint32_t) val.toInt();
  125. }
  126. else if (id == "DEBUG") { // Debug Level
  127. id_print(id, val);
  128. (*c).debug = (uint8_t) val.toInt();
  129. }
  130. else if (id == "PDEBUG") { // pDebug Pattern
  131. id_print(id, val);
  132. (*c).pdebug = (uint8_t) val.toInt();
  133. }
  134. else if (id == "CAD") { // CAD setting
  135. id_print(id, val);
  136. (*c).cad = (uint8_t) val.toInt();
  137. }
  138. else if (id == "HOP") { // HOP setting
  139. id_print(id, val);
  140. (*c).hop = (uint8_t) val.toInt();
  141. }
  142. else if (id == "BOOTS") { // BOOTS setting
  143. id_print(id, val);
  144. (*c).boots = (uint8_t) val.toInt();
  145. }
  146. else if (id == "RESETS") { // RESET setting
  147. id_print(id, val);
  148. (*c).resets = (uint8_t) val.toInt();
  149. }
  150. else if (id == "WIFIS") { // WIFIS setting
  151. id_print(id, val);
  152. (*c).wifis = (uint8_t) val.toInt();
  153. }
  154. else if (id == "VIEWS") { // VIEWS setting
  155. id_print(id, val);
  156. (*c).views = (uint8_t) val.toInt();
  157. }
  158. else if (id == "NODE") { // NODE setting
  159. id_print(id, val);
  160. (*c).isNode = (uint8_t) val.toInt();
  161. }
  162. else if (id == "REFR") { // REFR setting
  163. id_print(id, val);
  164. (*c).refresh = (uint8_t) val.toInt();
  165. }
  166. else if (id == "REENTS") { // REENTS setting
  167. id_print(id, val);
  168. (*c).reents = (uint8_t) val.toInt();
  169. }
  170. else if (id == "NTPERR") { // NTPERR setting
  171. id_print(id, val);
  172. (*c).ntpErr = (uint8_t) val.toInt();
  173. }
  174. else if (id == "NTPETIM") { // NTPERR setting
  175. id_print(id, val);
  176. (*c).ntpErrTime = (uint32_t) val.toInt();
  177. }
  178. else if (id == "NTPS") { // NTPS setting
  179. id_print(id, val);
  180. (*c).ntps = (uint8_t) val.toInt();
  181. }
  182. else if (id == "FILENO") { // FILENO setting
  183. id_print(id, val);
  184. (*c).logFileNo = (uint8_t) val.toInt();
  185. }
  186. else if (id == "FILEREC") { // FILEREC setting
  187. id_print(id, val);
  188. (*c).logFileRec = (uint16_t) val.toInt();
  189. }
  190. else if (id == "FILENUM") { // FILEREC setting
  191. id_print(id, val);
  192. (*c).logFileNum = (uint16_t) val.toInt();
  193. }
  194. else if (id == "EXPERT") { // EXPERT setting
  195. id_print(id, val);
  196. (*c).expert = (uint8_t) val.toInt();
  197. }
  198. else if (id == "DELAY") { // DELAY setting
  199. id_print(id, val);
  200. (*c).txDelay = (int32_t) val.toInt();
  201. }
  202. else if (id == "TRUSTED") { // TRUSTED setting
  203. id_print(id, val);
  204. (*c).trusted= (int32_t) val.toInt();
  205. }
  206. else {
  207. #if _DUSB>=1
  208. Serial.print(F("readConfig:: tries++"));
  209. #endif
  210. tries++;
  211. }
  212. }
  213. f.close();
  214. #if _DUSB>=1
  215. if (debug>=1) {
  216. Serial.println(F("readConfig:: Fini"));
  217. }
  218. Serial.println();
  219. #endif
  220. return(1);
  221. }//readConfig
  222. // ----------------------------------------------------------------------------
  223. // Write the current gateway configuration to SPIFFS. First copy all the
  224. // separate data items to the gwayConfig structure
  225. //
  226. // Note: gwayConfig.expert contains the expert setting already
  227. // gwayConfig.txDelay
  228. // ----------------------------------------------------------------------------
  229. int writeGwayCfg(const char *fn) {
  230. gwayConfig.ssid = WiFi.SSID();
  231. gwayConfig.pass = WiFi.psk(); // XXX We should find a way to store the password too
  232. gwayConfig.ch = ifreq; // Frequency Index
  233. gwayConfig.sf = (uint8_t) sf; // Spreading Factor
  234. gwayConfig.debug = debug;
  235. gwayConfig.pdebug = pdebug;
  236. gwayConfig.cad = _cad;
  237. gwayConfig.hop = _hop;
  238. #if GATEWAYNODE==1
  239. gwayConfig.fcnt = frameCount;
  240. #endif
  241. return(writeConfig(fn, &gwayConfig));
  242. }
  243. // ----------------------------------------------------------------------------
  244. // Write the configuration as found in the espGwayConfig structure
  245. // to SPIFFS
  246. // Parameters:
  247. // fn; Filename
  248. // c; struct config
  249. // Returns:
  250. // 1 when successful, -1 on error
  251. // ----------------------------------------------------------------------------
  252. int writeConfig(const char *fn, struct espGwayConfig *c) {
  253. // Assuming the cibfug file is the first we write...
  254. // If it is not there we should format first.
  255. // NOTE: Do not format for other files!
  256. if (!SPIFFS.exists(fn)) {
  257. Serial.print("WARNING:: writeConfig, file not exists, formatting ");
  258. SPIFFS.format();
  259. initConfig(c); // XXX make all initial declarations here if config vars need to have a value
  260. Serial.println(fn);
  261. }
  262. File f = SPIFFS.open(fn, "w");
  263. if (!f) {
  264. Serial.print("writeConfig: ERROR open file=");
  265. Serial.print(fn);
  266. Serial.println();
  267. return(-1);
  268. }
  269. f.print("SSID"); f.print('='); f.print((*c).ssid); f.print('\n');
  270. f.print("PASS"); f.print('='); f.print((*c).pass); f.print('\n');
  271. f.print("CH"); f.print('='); f.print((*c).ch); f.print('\n');
  272. f.print("SF"); f.print('='); f.print((*c).sf); f.print('\n');
  273. f.print("FCNT"); f.print('='); f.print((*c).fcnt); f.print('\n');
  274. f.print("DEBUG"); f.print('='); f.print((*c).debug); f.print('\n');
  275. f.print("PDEBUG"); f.print('='); f.print((*c).pdebug); f.print('\n');
  276. f.print("CAD"); f.print('='); f.print((*c).cad); f.print('\n');
  277. f.print("HOP"); f.print('='); f.print((*c).hop); f.print('\n');
  278. f.print("NODE"); f.print('='); f.print((*c).isNode); f.print('\n');
  279. f.print("BOOTS"); f.print('='); f.print((*c).boots); f.print('\n');
  280. f.print("RESETS"); f.print('='); f.print((*c).resets); f.print('\n');
  281. f.print("WIFIS"); f.print('='); f.print((*c).wifis); f.print('\n');
  282. f.print("VIEWS"); f.print('='); f.print((*c).views); f.print('\n');
  283. f.print("REFR"); f.print('='); f.print((*c).refresh); f.print('\n');
  284. f.print("REENTS"); f.print('='); f.print((*c).reents); f.print('\n');
  285. f.print("NTPETIM"); f.print('='); f.print((*c).ntpErrTime); f.print('\n');
  286. f.print("NTPERR"); f.print('='); f.print((*c).ntpErr); f.print('\n');
  287. f.print("NTPS"); f.print('='); f.print((*c).ntps); f.print('\n');
  288. f.print("FILEREC"); f.print('='); f.print((*c).logFileRec); f.print('\n');
  289. f.print("FILENO"); f.print('='); f.print((*c).logFileNo); f.print('\n');
  290. f.print("FILENUM"); f.print('='); f.print((*c).logFileNum); f.print('\n');
  291. f.print("DELAY"); f.print('='); f.print((*c).txDelay); f.print('\n');
  292. f.print("TRUSTED"); f.print('='); f.print((*c).trusted); f.print('\n');
  293. f.print("EXPERT"); f.print('='); f.print((*c).expert); f.print('\n');
  294. f.close();
  295. return(1);
  296. }
  297. // ----------------------------------------------------------------------------
  298. // Add a line with statistics to the log.
  299. //
  300. // We put the check in the function to protect against calling
  301. // the function without STAT_LOG being proper defined
  302. // ToDo: Store the fileNo and the fileRec in the status file to save for
  303. // restarts
  304. // Parameters:
  305. // line; char array with characters to write to log
  306. // cnt;
  307. // Returns:
  308. // <none>
  309. // ----------------------------------------------------------------------------
  310. int addLog(const unsigned char * line, int cnt)
  311. {
  312. #if STAT_LOG==1
  313. char fn[16];
  314. if (gwayConfig.logFileRec > LOGFILEREC) { // Have to make define for this
  315. gwayConfig.logFileRec = 0; // In new logFile start with record 0
  316. gwayConfig.logFileNo++; // Increase file ID
  317. gwayConfig.logFileNum++; // Increase number of log files
  318. }
  319. gwayConfig.logFileRec++;
  320. // If we have too many logfies, delete the oldest
  321. //
  322. if (gwayConfig.logFileNum > LOGFILEMAX){
  323. sprintf(fn,"/log-%d", gwayConfig.logFileNo - LOGFILEMAX);
  324. #if _DUSB>=1
  325. if (( debug>=0 ) && ( pdebug & P_GUI )) {
  326. Serial.print(F("G addLog:: Too many logfile, deleting="));
  327. Serial.println(fn);
  328. }
  329. #endif
  330. SPIFFS.remove(fn);
  331. gwayConfig.logFileNum--;
  332. }
  333. // Make sure we have the right fileno
  334. sprintf(fn,"/log-%d", gwayConfig.logFileNo);
  335. // If there is no SPIFFS, Error
  336. // Make sure to write the config record/line also
  337. if (!SPIFFS.exists(fn)) {
  338. #if _DUSB>=1
  339. if (( debug >= 1 ) && ( pdebug & P_GUI )) {
  340. Serial.print(F("G ERROR:: addLog:: file="));
  341. Serial.print(fn);
  342. Serial.print(F(" does not exist .. rec="));
  343. Serial.print(gwayConfig.logFileRec);
  344. Serial.println();
  345. }
  346. #endif
  347. }
  348. File f = SPIFFS.open(fn, "a");
  349. if (!f) {
  350. #if _DUSB>=1
  351. if (( debug>=1 ) && ( pdebug & P_GUI )) {
  352. Serial.println("G file open failed=");
  353. Serial.println(fn);
  354. }
  355. #endif
  356. return(0); // If file open failed, return
  357. }
  358. int i;
  359. #if _DUSB>=1
  360. if (( debug>=1 ) && ( pdebug & P_GUI )) {
  361. Serial.print(F("G addLog:: fileno="));
  362. Serial.print(gwayConfig.logFileNo);
  363. Serial.print(F(", rec="));
  364. Serial.print(gwayConfig.logFileRec);
  365. Serial.print(F(": "));
  366. #if _DUSB>=2
  367. for (i=0; i< 12; i++) { // The first 12 bytes contain non printable characters
  368. Serial.print(line[i],HEX);
  369. Serial.print(' ');
  370. }
  371. #else
  372. i+=12;
  373. #endif
  374. Serial.print((char *) &line[i]); // The rest if the buffer contains ascii
  375. Serial.println();
  376. }
  377. #endif //DUSB
  378. for (i=0; i< 12; i++) { // The first 12 bytes contain non printable characters
  379. // f.print(line[i],HEX);
  380. f.print('*');
  381. }
  382. f.write(&(line[i]), cnt-12); // write/append the line to the file
  383. f.print('\n');
  384. f.close(); // Close the file after appending to it
  385. #endif //STAT_LOG
  386. return(1);
  387. }
  388. // ----------------------------------------------------------------------------
  389. // Print (all) logfiles
  390. //
  391. // ----------------------------------------------------------------------------
  392. void printLog()
  393. {
  394. char fn[16];
  395. int i=0;
  396. #if _DUSB>=1
  397. while (i< LOGFILEMAX ) {
  398. sprintf(fn,"/log-%d", gwayConfig.logFileNo - i);
  399. if (!SPIFFS.exists(fn)) break; // break the loop
  400. // Open the file for reading
  401. File f = SPIFFS.open(fn, "r");
  402. int j;
  403. for (j=0; j<LOGFILEREC; j++) {
  404. String s=f.readStringUntil('\n');
  405. if (s.length() == 0) break;
  406. Serial.println(s.substring(12)); // Skip the first 12 Gateway specific binary characters
  407. yield();
  408. }
  409. i++;
  410. }
  411. #endif
  412. } //printLog
  413. #if _SEENMAX>0
  414. // ----------------------------------------------------------------------------
  415. // readSeen
  416. // This function read the stored information from writeSeen.
  417. //
  418. // Parameters:
  419. // Return:
  420. // ----------------------------------------------------------------------------
  421. int readSeen(const char *fn, struct nodeSeen *listSeen) {
  422. int i;
  423. if (!SPIFFS.exists(fn)) {
  424. #if _DUSB>=1
  425. Serial.print("WARNING:: readSeen, history file not exists ");
  426. #endif
  427. initSeen(listSeen); // XXX make all initial declarations here if config vars need to have a value
  428. Serial.println(fn);
  429. return(-1);
  430. }
  431. File f = SPIFFS.open(fn, "r");
  432. if (!f) {
  433. Serial.print("readConfig:: ERROR open file=");
  434. Serial.print(fn);
  435. Serial.println();
  436. return(-1);
  437. }
  438. for (i=0; i<_SEENMAX; i++) {
  439. String val;
  440. if (!f.available()) {
  441. #if _DUSB>=1
  442. Serial.println(F("readSeen:: No more info left in file"));
  443. #endif
  444. }
  445. val=f.readStringUntil('\t'); listSeen[i].timSeen = (uint32_t) val.toInt();
  446. val=f.readStringUntil('\t');
  447. listSeen[i].idSeen = (uint32_t) val.toInt();
  448. //listSeen[i].idSeen = strtoul(val, val.length()+1, 10);
  449. val=f.readStringUntil('\n'); listSeen[i].sfSeen = (uint8_t) val.toInt();
  450. }
  451. f.close();
  452. #if _DUSB>=1
  453. printSeen(listSeen);
  454. #endif
  455. }
  456. // ----------------------------------------------------------------------------
  457. // writeSeen
  458. // Once every few messages, update the SPIFFS file and write the array.
  459. // Parameters:
  460. // - fn contains the filename to write
  461. // - listSeen contains the _SEENMAX array of list structures
  462. // Return values:
  463. // - return 1 on success
  464. // ----------------------------------------------------------------------------
  465. int writeSeen(const char *fn, struct nodeSeen *listSeen) {
  466. int i;
  467. if (!SPIFFS.exists(fn)) {
  468. #if _DUSB>=1
  469. Serial.print("WARNING:: writeSeen, file not exists, formatting ");
  470. #endif
  471. initSeen(listSeen); // XXX make all initial declarations here if config vars need to have a value
  472. Serial.println(fn);
  473. }
  474. File f = SPIFFS.open(fn, "w");
  475. if (!f) {
  476. Serial.print("writeConfig:: ERROR open file=");
  477. Serial.print(fn);
  478. Serial.println();
  479. return(-1);
  480. }
  481. for (i=0; i<_SEENMAX; i++) {
  482. unsigned long timSeen;
  483. f.print(listSeen[i].timSeen); f.print('\t');
  484. // Typecast to long to avoid errors in unsigned conversion.
  485. f.print((long) listSeen[i].idSeen); f.print('\t');
  486. //f.print(listSeen[i].datSeen); f.print('\t');
  487. //f.print(listSeen[i].chanSeen); f.print('\t');
  488. //f.print(listSeen[i].rssiSeen); f.print('\t');
  489. f.print(listSeen[i].sfSeen); f.print('\n');
  490. }
  491. f.close();
  492. return(1);
  493. }
  494. // ----------------------------------------------------------------------------
  495. // printSeen
  496. // - Once every few messages, update the SPIFFS file and write the array.
  497. // ----------------------------------------------------------------------------
  498. int printSeen(struct nodeSeen *listSeen) {
  499. int i;
  500. #if _DUSB>=1
  501. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  502. Serial.println(F("printSeen:: "));
  503. for (i=0; i<_SEENMAX; i++) {
  504. if (listSeen[i].idSeen != 0) {
  505. String response;
  506. Serial.print(i);
  507. Serial.print(F(", TM="));
  508. stringTime(listSeen[i].timSeen, response);
  509. Serial.print(response);
  510. Serial.print(F(", addr=0x"));
  511. Serial.print(listSeen[i].idSeen,HEX);
  512. Serial.print(F(", SF=0x"));
  513. Serial.print(listSeen[i].sfSeen,HEX);
  514. Serial.println();
  515. }
  516. }
  517. }
  518. #endif
  519. return(1);
  520. }
  521. // ----------------------------------------------------------------------------
  522. // addSeen
  523. // With every new message received:
  524. // - Look whether the message is already in the array, if so update existing
  525. // message. If not, create new record.
  526. // - With this record, update the SF settings
  527. // ----------------------------------------------------------------------------
  528. int addSeen(struct nodeSeen *listSeen, uint32_t idSeen, uint8_t sfSeen, unsigned long timSeen) {
  529. int i;
  530. // ( message[4]<<24 | message[3]<<16 | message[2]<<8 | message[1] )
  531. #if _DUSB>=2
  532. if (( debug>=1 ) && ( pdebug & P_MAIN )) {
  533. Serial.print(F("addSeen:: "));
  534. // Serial.print(F(" listSeen[0]="));
  535. // Serial.print(listSeen[0].idSeen,HEX);
  536. // Serial.print(F(", "));
  537. Serial.print(F("tim=")); Serial.print(timSeen);
  538. Serial.print(F(", idSeen=")); Serial.print(idSeen,HEX);
  539. Serial.print(F(", sfSeen=")); Serial.print(sfSeen,HEX);
  540. Serial.println();
  541. }
  542. #endif
  543. for (i=0; i< _SEENMAX; i++) {
  544. if ((listSeen[i].idSeen==idSeen) ||
  545. (listSeen[i].idSeen==0))
  546. {
  547. #if _DUSB>=2
  548. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  549. Serial.print(F("addSeen:: index="));
  550. Serial.print(i);
  551. }
  552. #endif
  553. listSeen[i].idSeen = idSeen;
  554. listSeen[i].sfSeen |= sfSeen;
  555. listSeen[i].timSeen = timSeen;
  556. writeSeen(_SEENFILE, listSeen);
  557. break;
  558. }
  559. }
  560. if (i>=_SEENMAX) {
  561. #if _DUSB>=1
  562. if (( debug>=0 ) && ( pdebug & P_MAIN )) {
  563. Serial.print(F("addSeen:: exit=0, index="));
  564. Serial.println(i);
  565. }
  566. #endif
  567. return(0);
  568. }
  569. return(1);
  570. }
  571. // ----------------------------------------------------------------------------
  572. // initSeen
  573. // Init the lisrScreen array
  574. // ----------------------------------------------------------------------------
  575. int initSeen(struct nodeSeen *listSeen) {
  576. int i;
  577. for (i=0; i< _SEENMAX; i++) {
  578. listSeen[i].idSeen=0;
  579. listSeen[i].sfSeen=0;
  580. listSeen[i].timSeen=0;
  581. }
  582. return(1);
  583. }
  584. // ----------------------------------------------------------------------------
  585. // listDir
  586. // List the directory and put it in
  587. // ----------------------------------------------------------------------------
  588. void listDir(char * dir)
  589. {
  590. #if _DUSB>=1
  591. // Nothing here
  592. #endif
  593. }
  594. #endif //_SEENMAX>0