meteostanice.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. import { Database } from "bun:sqlite";
  2. import { nanoid } from 'nanoid'
  3. import generateSecureRandomString from "./generateSecureRandomString";
  4. const meteostaniceDB = new Database("./data/meteostanice.sqlite");
  5. meteostaniceDB.run(`create table if not exists list (
  6. id text not null primary key,
  7. owner text not null,
  8. name text not null,
  9. description text,
  10. websocketKey text not null,
  11. timestamp datetime default current_timestamp
  12. );`)
  13. meteostaniceDB.run(`create table if not exists data (
  14. id text not null primary key,
  15. meteostanica text not null,
  16. timestamp datetime default current_timestamp,
  17. indoorTemp text not null,
  18. indoorPressure text not null,
  19. indoorHumidity text not null,
  20. indoorAltitude text not null,
  21. outdoorConnected integer not null,
  22. outdoorTemp text not null,
  23. outdoorPressure text not null,
  24. outdoorHumidity text not null,
  25. outdoorAltitude text not null
  26. );`)
  27. meteostaniceDB.run(`create table if not exists public (
  28. id text not null primary key,
  29. name text not null,
  30. description text,
  31. timestamp datetime default current_timestamp,
  32. showOwner integer default 1,
  33. showIndoorTemp integer default 1,
  34. showIndoorPressure integer default 1,
  35. showIndoorHumidity integer default 1,
  36. showIndoorAltitude integer default 1,
  37. showOutdoorConnected integer default 1,
  38. showOutdoorTemp integer default 1,
  39. showOutdoorPressure integer default 1,
  40. showOutdoorHumidity integer default 1,
  41. showOutdoorAltitude integer default 1
  42. );`)
  43. export default class Meteostanice {
  44. static add(owner, name, description) {
  45. const id = nanoid()
  46. const websocketKey = generateSecureRandomString()
  47. meteostaniceDB.prepare(`
  48. INSERT INTO list (id, owner, name, description, websocketKey)
  49. VALUES (?, ?, ?, ?, ?);
  50. `).run(id, owner, name, description, websocketKey)
  51. }
  52. static get(owner, id) {
  53. const statement = meteostaniceDB.prepare(`
  54. SELECT *
  55. FROM list
  56. WHERE owner = $owner AND id = $id;
  57. `)
  58. const result = statement.get({
  59. $owner: owner,
  60. $id: id
  61. });
  62. return result
  63. }
  64. static getWebsocket(key) {
  65. const statement = meteostaniceDB.prepare(`
  66. SELECT *
  67. FROM list
  68. WHERE websocketKey = $key;
  69. `)
  70. const result = statement.get({
  71. $key: key
  72. });
  73. return result
  74. }
  75. static getOwned(owner) {
  76. const statement = meteostaniceDB.prepare(`
  77. SELECT *
  78. FROM list
  79. WHERE owner = $owner
  80. ORDER BY timestamp DESC;
  81. `)
  82. const result = statement.all({
  83. $owner: owner
  84. });
  85. return result
  86. }
  87. static edit(id, newName, newDescription, newOwner) {
  88. meteostaniceDB.prepare(`
  89. update list
  90. set name = ?,
  91. description = ?,
  92. owner = ?
  93. where id = ?;
  94. `).run(newName, newDescription, newOwner, id)
  95. }
  96. static editOwnerOnOwned(owner, newOwner) {
  97. meteostaniceDB.prepare(`
  98. update list
  99. set owner = ?
  100. where owner = ?;
  101. `).run(newOwner, owner)
  102. }
  103. static delete(id) {
  104. meteostaniceDB.prepare(`
  105. DELETE
  106. FROM data
  107. WHERE meteostanica = $id;
  108. `).run({
  109. $id: id
  110. });
  111. meteostaniceDB.prepare(`
  112. DELETE
  113. FROM public
  114. WHERE id = $id;
  115. `).run({
  116. $id: id
  117. });
  118. meteostaniceDB.prepare(`
  119. DELETE
  120. FROM list
  121. WHERE id = $id;
  122. `).run({
  123. $id: id
  124. });
  125. }
  126. static deleteOwned(owner) {
  127. const meteostanice = this.getOwned(owner)
  128. for (const meteostanica of meteostanice) {
  129. this.delete(meteostanica.owner, meteostanica.id)
  130. }
  131. }
  132. static postData(meteostanica, indoorTemp, indoorPressure, indoorHumidity, indoorAltitude, outdoorConnected, outdoorTemp, outdoorPressure, outdoorHumidity, outdoorAltitude) {
  133. const id = nanoid()
  134. meteostaniceDB.prepare(`
  135. INSERT INTO data (id, meteostanica, indoorTemp, indoorPressure, indoorHumidity, indoorAltitude, outdoorConnected, outdoorTemp, outdoorPressure, outdoorHumidity, outdoorAltitude)
  136. VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
  137. `).run(id, meteostanica, indoorTemp, indoorPressure, indoorHumidity, indoorAltitude, outdoorConnected, outdoorTemp, outdoorPressure, outdoorHumidity, outdoorAltitude)
  138. }
  139. static getData(meteostanica) {
  140. const statement = meteostaniceDB.prepare(`
  141. SELECT *
  142. FROM data
  143. WHERE meteostanica = $meteostanica
  144. ORDER BY timestamp DESC;
  145. `)
  146. const result = statement.all({
  147. $meteostanica: meteostanica
  148. });
  149. return result
  150. }
  151. static getDataProperty(meteostanica, property) {
  152. const tableNames = meteostanicaDB.prepare(`PRAGMA table_info('data');`).all()
  153. if (!tableNames.find(i => i.name === property)) return null
  154. const statement = meteostanicaDB.prepare(`
  155. SELECT ${property}
  156. FROM data
  157. WHERE meteostanica = $meteostanica
  158. ORDER BY timestamp DESC
  159. LIMIT 10;
  160. `)
  161. const result = statement.all({
  162. $meteostanica: meteostanica
  163. });
  164. return result
  165. }
  166. static getDataPropertyDaily(meteostanica, property, date) {
  167. const tableNames = meteostanicaDB.prepare(`PRAGMA table_info('data');`).all()
  168. if (!tableNames.find(i => i.name === property)) return null
  169. const statement = meteostanicaDB.prepare(`
  170. SELECT strftime('%Y-%m-%d %H:00:00', timestamp) AS timeMark,
  171. AVG(${property}) AS value
  172. FROM data
  173. WHERE meteostanica = ? AND date(timestamp) = ? -- Pass 'YYYY-MM-DD' here
  174. GROUP BY timeMark
  175. ORDER BY timeMark;
  176. `)
  177. const result = statement.all(meteostanica, date);
  178. return result
  179. }
  180. static getDataPropertyMonthly(meteostanica, property, yearMonth) {
  181. const tableNames = meteostanicaDB.prepare(`PRAGMA table_info('data');`).all()
  182. if (!tableNames.find(i => i.name === property)) return null
  183. const statement = meteostanicaDB.prepare(`
  184. SELECT date(timestamp) AS timeMark,
  185. AVG(${property}) AS value
  186. FROM data
  187. WHERE meteostanica = ? AND strftime('%Y-%m', timestamp) = ? -- Pass 'YYYY-MM' here
  188. GROUP BY timeMark
  189. ORDER BY timeMark;
  190. `)
  191. const result = statement.all(meteostanica, yearMonth);
  192. return result
  193. }
  194. static getDataPropertyYearly(meteostanica, property, year) {
  195. const tableNames = meteostanicaDB.prepare(`PRAGMA table_info('data');`).all()
  196. if (!tableNames.find(i => i.name === property)) return null
  197. const statement = meteostanicaDB.prepare(`
  198. SELECT strftime('%Y-%m', timestamp) AS timeMark,
  199. AVG(${property}) AS value
  200. FROM data
  201. WHERE meteostanica = ? AND strftime('%Y', timestamp) = ? -- Pass 'YYYY' here
  202. GROUP BY timeMark
  203. ORDER BY timeMark;
  204. `)
  205. const result = statement.all(meteostanica, year);
  206. return result
  207. }
  208. static getDataPropertyAllTime(meteostanica, property) {
  209. const tableNames = meteostanicaDB.prepare(`PRAGMA table_info('data');`).all()
  210. if (!tableNames.find(i => i.name === property)) return null
  211. const statement = meteostanicaDB.prepare(`
  212. SELECT strftime('%Y', timestamp) AS timeMark,
  213. AVG(${property}) AS value
  214. FROM data
  215. WHERE meteostanica = ?
  216. GROUP BY timeMark
  217. ORDER BY timeMark;
  218. `)
  219. const result = statement.all(meteostanica);
  220. return result
  221. }
  222. static getDateMap(meteostanica) {
  223. const statement = meteostanicaDB.query("SELECT DISTINCT date(timestamp) as d FROM data WHERE meteostanica = ? ORDER BY d ASC");
  224. const rows = statement.all(meteostanica);
  225. return rows.reduce((acc, row) => {
  226. const [year, month, day] = row.d.split("-");
  227. if (!acc[year]) acc[year] = {};
  228. if (!acc[year][month]) acc[year][month] = [];
  229. acc[year][month].push(day);
  230. return acc;
  231. }, {});
  232. }
  233. static resetWebsocketKey(id) {
  234. const websocketKey = generateSecureRandomString()
  235. meteostaniceDB.prepare(`
  236. update list
  237. set websocketKey = ?
  238. where id = ?;
  239. `).run(websocketKey, id)
  240. }
  241. }