cpXXtime2a.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. #include "iec_include.h"
  2. #include "mmodbus.h"
  3. typedef uint64_t time_t;
  4. struct tm {
  5. int tm_sec;
  6. int tm_min;
  7. int tm_hour;
  8. int tm_mday;
  9. int tm_mon;
  10. int tm_year;
  11. int tm_wday;
  12. int tm_yday;
  13. int tm_isdst;
  14. };
  15. bool
  16. CP16Time2a_getFromBuffer (CP16Time2a self, const uint8_t* msg, int msgSize, int startIndex)
  17. {
  18. if (msgSize < startIndex + 2)
  19. return false;
  20. int i;
  21. for (i = 0; i < 2; i++)
  22. self->encodedValue[i] = msg[startIndex + i];
  23. return true;
  24. }
  25. int
  26. CP16Time2a_getEplapsedTimeInMs(const CP16Time2a self)
  27. {
  28. return (self->encodedValue[0] + (self->encodedValue[1] * 0x100));
  29. }
  30. void
  31. CP16Time2a_setEplapsedTimeInMs(CP16Time2a self, int value)
  32. {
  33. self->encodedValue[0] = (uint8_t) (value % 0x100);
  34. self->encodedValue[1] = (uint8_t) (value / 0x100);
  35. }
  36. uint8_t*
  37. CP16Time2a_getEncodedValue(CP16Time2a self)
  38. {
  39. return self->encodedValue;
  40. }
  41. /************************************
  42. * CP24Time2a and CP26Time2a common
  43. ************************************/
  44. static int
  45. getMillisecond(const uint8_t* encodedValue)
  46. {
  47. return (encodedValue[0] + (encodedValue[1] * 0x100)) % 1000;
  48. }
  49. static void
  50. setMillisecond(uint8_t* encodedValue, int value)
  51. {
  52. int millies = encodedValue[0] + (encodedValue[1] * 0x100);
  53. /* erase sub-second part */
  54. millies = millies - (millies % 1000);
  55. millies = millies + value;
  56. encodedValue[0] = (uint8_t) (millies & 0xff);
  57. encodedValue[1] = (uint8_t) ((millies / 0x100) & 0xff);
  58. }
  59. static int
  60. getSecond(const uint8_t* encodedValue)
  61. {
  62. return (encodedValue[0] + (encodedValue[1] * 0x100)) / 1000;
  63. }
  64. static void
  65. setSecond(uint8_t* encodedValue, int value)
  66. {
  67. int millies = encodedValue[0] + (encodedValue[1] * 0x100);
  68. int msPart = millies % 1000;
  69. millies = (value * 1000) + msPart;
  70. encodedValue[0] = (uint8_t) (millies & 0xff);
  71. encodedValue[1] = (uint8_t) ((millies / 0x100) & 0xff);
  72. }
  73. static int
  74. getMinute(const uint8_t* encodedValue)
  75. {
  76. return (encodedValue[2] & 0x3f);
  77. }
  78. static void
  79. setMinute(uint8_t* encodedValue, int value)
  80. {
  81. encodedValue[2] = (uint8_t) ((encodedValue[2] & 0xc0) | (value & 0x3f));
  82. }
  83. static bool
  84. isInvalid(const uint8_t* encodedValue)
  85. {
  86. return ((encodedValue[2] & 0x80) != 0);
  87. }
  88. static void
  89. setInvalid(uint8_t* encodedValue, bool value)
  90. {
  91. if (value)
  92. encodedValue[2] |= 0x80;
  93. else
  94. encodedValue[2] &= 0x7f;
  95. }
  96. static bool
  97. isSubstituted(const uint8_t* encodedValue)
  98. {
  99. return ((encodedValue[2] & 0x40) == 0x40);
  100. }
  101. static void
  102. setSubstituted(uint8_t* encodedValue, bool value)
  103. {
  104. if (value)
  105. encodedValue[2] |= 0x40;
  106. else
  107. encodedValue[2] &= 0xbf;
  108. }
  109. /**********************************
  110. * CP24Time2a type
  111. **********************************/
  112. bool
  113. CP24Time2a_getFromBuffer (CP24Time2a self, const uint8_t* msg, int msgSize, int startIndex)
  114. {
  115. if (msgSize < startIndex + 3)
  116. return false;
  117. int i;
  118. for (i = 0; i < 3; i++)
  119. self->encodedValue[i] = msg[startIndex + i];
  120. return true;
  121. }
  122. int
  123. CP24Time2a_getMillisecond(const CP24Time2a self)
  124. {
  125. return getMillisecond(self->encodedValue);
  126. }
  127. void
  128. CP24Time2a_setMillisecond(CP24Time2a self, int value)
  129. {
  130. setMillisecond(self->encodedValue, value);
  131. }
  132. int
  133. CP24Time2a_getSecond(const CP24Time2a self)
  134. {
  135. return getSecond(self->encodedValue);
  136. }
  137. void
  138. CP24Time2a_setSecond(CP24Time2a self, int value)
  139. {
  140. setSecond(self->encodedValue, value);
  141. }
  142. int
  143. CP24Time2a_getMinute(const CP24Time2a self)
  144. {
  145. return getMinute(self->encodedValue);
  146. }
  147. void
  148. CP24Time2a_setMinute(CP24Time2a self, int value)
  149. {
  150. setMinute(self->encodedValue, value);
  151. }
  152. bool
  153. CP24Time2a_isInvalid(const CP24Time2a self)
  154. {
  155. return isInvalid(self->encodedValue);
  156. }
  157. void
  158. CP24Time2a_setInvalid(CP24Time2a self, bool value)
  159. {
  160. setInvalid(self->encodedValue, value);
  161. }
  162. bool
  163. CP24Time2a_isSubstituted(const CP24Time2a self)
  164. {
  165. return isSubstituted(self->encodedValue);
  166. }
  167. void
  168. CP24Time2a_setSubstituted(CP24Time2a self, bool value)
  169. {
  170. setSubstituted(self->encodedValue, value);
  171. }
  172. #if 0
  173. /* function found here: http://stackoverflow.com/questions/530519/stdmktime-and-timezone-info */
  174. time_t my_timegm(register struct tm * t)
  175. /* struct tm to seconds since Unix epoch */
  176. {
  177. register long year;
  178. register time_t result;
  179. #define MONTHSPERYEAR 12 /* months per calendar year */
  180. static const int cumdays[MONTHSPERYEAR] =
  181. { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  182. /*@ +matchanyintegral @*/
  183. year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR;
  184. result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR];
  185. result += (year - 1968) / 4;
  186. result -= (year - 1900) / 100;
  187. result += (year - 1600) / 400;
  188. if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) &&
  189. (t->tm_mon % MONTHSPERYEAR) < 2)
  190. result--;
  191. result += t->tm_mday - 1;
  192. result *= 24;
  193. result += t->tm_hour;
  194. result *= 60;
  195. result += t->tm_min;
  196. result *= 60;
  197. result += t->tm_sec;
  198. if (t->tm_isdst == 1)
  199. result -= 3600;
  200. /*@ -matchanyintegral @*/
  201. return (result);
  202. }
  203. #endif
  204. /* Conversion from UTC date to second, unsigned 32-bit Unix epoch version.
  205. * Written by François Grieu, 2015-07-21; public domain.
  206. *
  207. * my_mktime converts from struct tm UTC to non-leap seconds since
  208. * 00:00:00 on the first UTC day of year 1970 (fixed).
  209. * It works from 1970 to 2105 inclusive. It strives to be compatible
  210. * with C compilers supporting // comments and claiming C89 conformance.
  211. *
  212. * input: Pointer to a struct tm with field tm_year, tm_mon, tm_mday,
  213. * tm_hour, tm_min, tm_sec set per mktime convention; thus
  214. * - tm_year is year minus 1900
  215. * - tm_mon is [0..11] for January to December, but [-2..14]
  216. * works for November of previous year to February of next year
  217. * - tm_mday, tm_hour, tm_min, tm_sec similarly can be offset to
  218. * the full range [-32767 to 32768], as long as the combination
  219. * with tm_year gives a result within years [1970..2105], and
  220. * tm_year>0.
  221. * output: Number of non-leap seconds since beginning of the first UTC
  222. * day of year 1970, as an unsigned at-least-32-bit integer.
  223. * The input is not changed (in particular, fields tm_wday,
  224. * tm_yday, and tm_isdst are unchanged and ignored).
  225. */
  226. static time_t
  227. my_mktime(const struct tm * ptm)
  228. {
  229. int m, y = ptm->tm_year;
  230. if ((m = ptm->tm_mon) < 2) {
  231. m += 12;
  232. --y;
  233. }
  234. return ((((time_t) (y - 69) * 365u + y / 4 - y / 100 * 3 / 4 + (m + 2) * 153 / 5 - 446 +
  235. ptm->tm_mday) * 24u + ptm->tm_hour) * 60u + ptm->tm_min) * 60u + ptm->tm_sec;
  236. }
  237. /**********************************
  238. * CP32Time2a type
  239. **********************************/
  240. CP32Time2a
  241. CP32Time2a_create(CP32Time2a self)
  242. {
  243. if (self == NULL)
  244. self = (CP32Time2a) GLOBAL_CALLOC(1, sizeof(struct sCP32Time2a));
  245. else
  246. memset (self, 0, sizeof(struct sCP32Time2a));
  247. return self;
  248. }
  249. bool
  250. CP32Time2a_getFromBuffer (CP32Time2a self, const uint8_t* msg, int msgSize, int startIndex)
  251. {
  252. if (msgSize < startIndex + 4)
  253. return false;
  254. int i;
  255. for (i = 0; i < 4; i++)
  256. self->encodedValue[i] = msg[startIndex + i];
  257. return true;
  258. }
  259. int
  260. CP32Time2a_getMillisecond(const CP32Time2a self)
  261. {
  262. return (self->encodedValue[0] + (self->encodedValue[1] * 0x100)) % 1000;
  263. }
  264. void
  265. CP32Time2a_setMillisecond(CP32Time2a self, int value)
  266. {
  267. int millies = (CP32Time2a_getSecond(self) * 1000) + value;
  268. self->encodedValue[0] = (uint8_t) (millies & 0xff);
  269. self->encodedValue[1] = (uint8_t) ((millies / 0x100) & 0xff);
  270. }
  271. int
  272. CP32Time2a_getSecond(const CP32Time2a self)
  273. {
  274. return getSecond(self->encodedValue);
  275. }
  276. void
  277. CP32Time2a_setSecond(CP32Time2a self, int value)
  278. {
  279. setSecond(self->encodedValue, value);
  280. }
  281. int
  282. CP32Time2a_getMinute(const CP32Time2a self)
  283. {
  284. return getMinute(self->encodedValue);
  285. }
  286. void
  287. CP32Time2a_setMinute(CP32Time2a self, int value)
  288. {
  289. setMinute(self->encodedValue, value);
  290. }
  291. bool
  292. CP32Time2a_isInvalid(const CP32Time2a self)
  293. {
  294. return isInvalid(self->encodedValue);
  295. }
  296. void
  297. CP32Time2a_setInvalid(CP32Time2a self, bool value)
  298. {
  299. setInvalid(self->encodedValue, value);
  300. }
  301. bool
  302. CP32Time2a_isSubstituted(const CP32Time2a self)
  303. {
  304. return isSubstituted(self->encodedValue);
  305. }
  306. void
  307. CP32Time2a_setSubstituted(CP32Time2a self, bool value)
  308. {
  309. setSubstituted(self->encodedValue, value);
  310. }
  311. int
  312. CP32Time2a_getHour(const CP32Time2a self)
  313. {
  314. return (self->encodedValue[3] & 0x1f);
  315. }
  316. void
  317. CP32Time2a_setHour(CP32Time2a self, int value)
  318. {
  319. self->encodedValue[3] = (uint8_t) ((self->encodedValue[3] & 0xe0) | (value & 0x1f));
  320. }
  321. bool
  322. CP32Time2a_isSummerTime(const CP32Time2a self)
  323. {
  324. return ((self->encodedValue[3] & 0x80) != 0);
  325. }
  326. void
  327. CP32Time2a_setSummerTime(CP32Time2a self, bool value)
  328. {
  329. if (value)
  330. self->encodedValue[3] |= 0x80;
  331. else
  332. self->encodedValue[3] &= 0x7f;
  333. }
  334. void
  335. CP32Time2a_setFromMsTimestamp(CP32Time2a self, uint64_t timestamp)
  336. {
  337. memset(self->encodedValue, 0, 4);
  338. time_t timeVal = timestamp / 1000;
  339. int msPart = timestamp % 1000;
  340. struct tm tmTime;
  341. //#ifdef _WIN32
  342. // gmtime_s(&tmTime, &timeVal);
  343. //#else
  344. // gmtime_r(&timeVal, &tmTime);
  345. //#endif
  346. CP32Time2a_setSecond(self, tmTime.tm_sec);
  347. CP32Time2a_setMillisecond(self, msPart);
  348. CP32Time2a_setMinute(self, tmTime.tm_min);
  349. CP32Time2a_setHour(self, tmTime.tm_hour);
  350. }
  351. uint8_t*
  352. CP32Time2a_getEncodedValue(CP32Time2a self)
  353. {
  354. return self->encodedValue;
  355. }
  356. /**********************************
  357. * CP56Time2a type
  358. **********************************/
  359. CP56Time2a
  360. CP56Time2a_createFromMsTimestamp(CP56Time2a self, uint64_t timestamp)
  361. {
  362. if (self == NULL)
  363. self = (CP56Time2a) GLOBAL_CALLOC(1, sizeof(struct sCP56Time2a));
  364. else
  365. memset (self, 0, sizeof(struct sCP56Time2a));
  366. if (self != NULL)
  367. CP56Time2a_setFromMsTimestamp(self, timestamp);
  368. return self;
  369. }
  370. void
  371. CP56Time2a_setFromMsTimestamp(CP56Time2a self, uint64_t timestamp)
  372. {
  373. memset(self->encodedValue, 0, 7);
  374. time_t timeVal = timestamp / 1000;
  375. int msPart = timestamp % 1000;
  376. struct tm tmTime;
  377. /* TODO replace with portable implementation */
  378. //#ifdef _WIN32
  379. //gmtime_s(&tmTime, &timeVal);
  380. //#else
  381. // gmtime_r(&timeVal, &tmTime);
  382. //#endif
  383. CP56Time2a_setMillisecond(self, msPart);
  384. CP56Time2a_setSecond(self, tmTime.tm_sec);
  385. CP56Time2a_setMinute(self, tmTime.tm_min);
  386. CP56Time2a_setHour(self, tmTime.tm_hour);
  387. CP56Time2a_setDayOfMonth(self, tmTime.tm_mday);
  388. /* set day of week to 0 = not present */
  389. CP56Time2a_setDayOfWeek(self, 0);
  390. CP56Time2a_setMonth(self, tmTime.tm_mon + 1);
  391. CP56Time2a_setYear(self, tmTime.tm_year);
  392. }
  393. uint64_t
  394. CP56Time2a_toMsTimestamp(const CP56Time2a self)
  395. {
  396. struct tm tmTime;
  397. tmTime.tm_sec = CP56Time2a_getSecond(self);
  398. tmTime.tm_min = CP56Time2a_getMinute(self);
  399. tmTime.tm_hour = CP56Time2a_getHour(self);
  400. tmTime.tm_mday = CP56Time2a_getDayOfMonth(self);
  401. tmTime.tm_mon = CP56Time2a_getMonth(self) - 1;
  402. tmTime.tm_year = CP56Time2a_getYear(self) + 100;
  403. time_t timestamp = my_mktime(&tmTime);
  404. uint64_t msTimestamp = ((uint64_t) (timestamp * (uint64_t) 1000)) + CP56Time2a_getMillisecond(self);
  405. return msTimestamp;
  406. }
  407. /* private */ bool
  408. CP56Time2a_getFromBuffer(CP56Time2a self, const uint8_t* msg, int msgSize, int startIndex)
  409. {
  410. if (msgSize < startIndex + 7)
  411. return false;
  412. int i;
  413. for (i = 0; i < 7; i++)
  414. self->encodedValue[i] = msg[startIndex + i];
  415. return true;
  416. }
  417. int
  418. CP56Time2a_getMillisecond(const CP56Time2a self)
  419. {
  420. return getMillisecond(self->encodedValue);
  421. }
  422. void
  423. CP56Time2a_setMillisecond(CP56Time2a self, int value)
  424. {
  425. setMillisecond(self->encodedValue, value);
  426. }
  427. int
  428. CP56Time2a_getSecond(const CP56Time2a self)
  429. {
  430. return getSecond(self->encodedValue);
  431. }
  432. void
  433. CP56Time2a_setSecond(CP56Time2a self, int value)
  434. {
  435. setSecond(self->encodedValue, value);
  436. }
  437. int
  438. CP56Time2a_getMinute(const CP56Time2a self)
  439. {
  440. return getMinute(self->encodedValue);
  441. }
  442. void
  443. CP56Time2a_setMinute(CP56Time2a self, int value)
  444. {
  445. setMinute(self->encodedValue, value);
  446. }
  447. int
  448. CP56Time2a_getHour(const CP56Time2a self)
  449. {
  450. return (self->encodedValue[3] & 0x1f);
  451. }
  452. void
  453. CP56Time2a_setHour(CP56Time2a self, int value)
  454. {
  455. self->encodedValue[3] = (uint8_t) ((self->encodedValue[3] & 0xe0) | (value & 0x1f));
  456. }
  457. int
  458. CP56Time2a_getDayOfWeek(const CP56Time2a self)
  459. {
  460. return ((self->encodedValue[4] & 0xe0) >> 5);
  461. }
  462. void
  463. CP56Time2a_setDayOfWeek(CP56Time2a self, int value)
  464. {
  465. self->encodedValue[4] = (uint8_t) ((self->encodedValue[4] & 0x1f) | ((value & 0x07) << 5));
  466. }
  467. int
  468. CP56Time2a_getDayOfMonth(const CP56Time2a self)
  469. {
  470. return (self->encodedValue[4] & 0x1f);
  471. }
  472. void
  473. CP56Time2a_setDayOfMonth(CP56Time2a self, int value)
  474. {
  475. self->encodedValue[4] = (uint8_t) ((self->encodedValue[4] & 0xe0) + (value & 0x1f));
  476. }
  477. int
  478. CP56Time2a_getMonth(const CP56Time2a self)
  479. {
  480. return (self->encodedValue[5] & 0x0f);
  481. }
  482. void
  483. CP56Time2a_setMonth(CP56Time2a self, int value)
  484. {
  485. self->encodedValue[5] = (uint8_t) ((self->encodedValue[5] & 0xf0) + (value & 0x0f));
  486. }
  487. int
  488. CP56Time2a_getYear(const CP56Time2a self)
  489. {
  490. return (self->encodedValue[6] & 0x7f);
  491. }
  492. void
  493. CP56Time2a_setYear(CP56Time2a self, int value)
  494. {
  495. value = value % 100;
  496. self->encodedValue[6] = (uint8_t) ((self->encodedValue[6] & 0x80) + (value & 0x7f));
  497. }
  498. bool
  499. CP56Time2a_isSummerTime(const CP56Time2a self)
  500. {
  501. return ((self->encodedValue[3] & 0x80) != 0);
  502. }
  503. void
  504. CP56Time2a_setSummerTime(CP56Time2a self, bool value)
  505. {
  506. if (value)
  507. self->encodedValue[3] |= 0x80;
  508. else
  509. self->encodedValue[3] &= 0x7f;
  510. }
  511. bool
  512. CP56Time2a_isInvalid(const CP56Time2a self)
  513. {
  514. return isInvalid(self->encodedValue);
  515. }
  516. void
  517. CP56Time2a_setInvalid(CP56Time2a self, bool value)
  518. {
  519. setInvalid(self->encodedValue, value);
  520. }
  521. bool
  522. CP56Time2a_isSubstituted(const CP56Time2a self)
  523. {
  524. return isSubstituted(self->encodedValue);
  525. }
  526. void
  527. CP56Time2a_setSubstituted(CP56Time2a self, bool value)
  528. {
  529. setSubstituted(self->encodedValue, value);
  530. }
  531. uint8_t*
  532. CP56Time2a_getEncodedValue(CP56Time2a self)
  533. {
  534. return self->encodedValue;
  535. }