diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index 44fa6b4..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,3 +0,0 @@ -[alias] -format = "+nightly fmt" -lint = "clippy --all-targets --all-features -- -D warnings" diff --git a/.env.example b/.env.example deleted file mode 100644 index f86ad04..0000000 --- a/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -#EMGAUWA_CONTROLLER__LOGGING__LEVEL=DEBUG - -#EMGAUWA_CORE__LOGGING__LEVEL=DEBUG diff --git a/.sqlx/query-03bfe5bd71d673a621b6ad6af5f71bf18ede519e6b950933f6751ef9cf7521c9.json b/.sqlx/query-03bfe5bd71d673a621b6ad6af5f71bf18ede519e6b950933f6751ef9cf7521c9.json deleted file mode 100644 index ce5073b..0000000 Binary files a/.sqlx/query-03bfe5bd71d673a621b6ad6af5f71bf18ede519e6b950933f6751ef9cf7521c9.json and /dev/null differ diff --git a/.sqlx/query-0874e71c6206efc82528cc450bc86549c43e9be2f4ac3b257e836187fa9ed080.json b/.sqlx/query-0874e71c6206efc82528cc450bc86549c43e9be2f4ac3b257e836187fa9ed080.json deleted file mode 100644 index 9b1f908..0000000 Binary files a/.sqlx/query-0874e71c6206efc82528cc450bc86549c43e9be2f4ac3b257e836187fa9ed080.json and /dev/null differ diff --git a/.sqlx/query-08c517120fcfb4534a3ff540910417afca55278e269f12203f4fc83096944810.json b/.sqlx/query-08c517120fcfb4534a3ff540910417afca55278e269f12203f4fc83096944810.json deleted file mode 100644 index b29819b..0000000 Binary files a/.sqlx/query-08c517120fcfb4534a3ff540910417afca55278e269f12203f4fc83096944810.json and /dev/null differ diff --git a/.sqlx/query-1348af1c13719ffcd72c2a4c6712b2bab2a9923c715295d8b1d937d33844d1a4.json b/.sqlx/query-1348af1c13719ffcd72c2a4c6712b2bab2a9923c715295d8b1d937d33844d1a4.json deleted file mode 100644 index f7313fd..0000000 Binary files a/.sqlx/query-1348af1c13719ffcd72c2a4c6712b2bab2a9923c715295d8b1d937d33844d1a4.json and /dev/null differ diff --git a/.sqlx/query-1cb4cc57ff361d6d84a0c8e8f5df1ff46abbb21dfc3eb3f4f38b251f99d10abd.json b/.sqlx/query-1cb4cc57ff361d6d84a0c8e8f5df1ff46abbb21dfc3eb3f4f38b251f99d10abd.json deleted file mode 100644 index 5be1688..0000000 Binary files a/.sqlx/query-1cb4cc57ff361d6d84a0c8e8f5df1ff46abbb21dfc3eb3f4f38b251f99d10abd.json and /dev/null differ diff --git a/.sqlx/query-1eda8cf54e553e8e892ac63a31cb94e91e7851a53ebae17a26b19300b83d7dac.json b/.sqlx/query-1eda8cf54e553e8e892ac63a31cb94e91e7851a53ebae17a26b19300b83d7dac.json deleted file mode 100644 index e3769c9..0000000 Binary files a/.sqlx/query-1eda8cf54e553e8e892ac63a31cb94e91e7851a53ebae17a26b19300b83d7dac.json and /dev/null differ diff --git a/.sqlx/query-20e99a281e5e3e9c9d7375425d93d15ccf840e9f469007d37b6eb47f96f31dc7.json b/.sqlx/query-20e99a281e5e3e9c9d7375425d93d15ccf840e9f469007d37b6eb47f96f31dc7.json deleted file mode 100644 index 776039b..0000000 Binary files a/.sqlx/query-20e99a281e5e3e9c9d7375425d93d15ccf840e9f469007d37b6eb47f96f31dc7.json and /dev/null differ diff --git a/.sqlx/query-2551c285e3e223311cff8e32022d8b11e95d56b2f166326301a0b6722fc1fd44.json b/.sqlx/query-2551c285e3e223311cff8e32022d8b11e95d56b2f166326301a0b6722fc1fd44.json deleted file mode 100644 index f6f2724..0000000 Binary files a/.sqlx/query-2551c285e3e223311cff8e32022d8b11e95d56b2f166326301a0b6722fc1fd44.json and /dev/null differ diff --git a/.sqlx/query-2e3528a386066c3fc11be1259298f281279353d0b92625c46ef5cd09a672c031.json b/.sqlx/query-2e3528a386066c3fc11be1259298f281279353d0b92625c46ef5cd09a672c031.json deleted file mode 100644 index fe474ae..0000000 Binary files a/.sqlx/query-2e3528a386066c3fc11be1259298f281279353d0b92625c46ef5cd09a672c031.json and /dev/null differ diff --git a/.sqlx/query-3adb7ab9cacd5a84d882e4c9860be83d32bb0380b1fb76f90bf4e200636c7f6a.json b/.sqlx/query-3adb7ab9cacd5a84d882e4c9860be83d32bb0380b1fb76f90bf4e200636c7f6a.json deleted file mode 100644 index 59ce879..0000000 Binary files a/.sqlx/query-3adb7ab9cacd5a84d882e4c9860be83d32bb0380b1fb76f90bf4e200636c7f6a.json and /dev/null differ diff --git a/.sqlx/query-3b5a701d0ace12125c573680bcd5d9768b3709b347afb04c329b8fb1d3972111.json b/.sqlx/query-3b5a701d0ace12125c573680bcd5d9768b3709b347afb04c329b8fb1d3972111.json deleted file mode 100644 index 390622e..0000000 Binary files a/.sqlx/query-3b5a701d0ace12125c573680bcd5d9768b3709b347afb04c329b8fb1d3972111.json and /dev/null differ diff --git a/.sqlx/query-3fe383ea9ed4965e25d54eea08fb5abbab1b0c8eec7cf11597267de780299d0d.json b/.sqlx/query-3fe383ea9ed4965e25d54eea08fb5abbab1b0c8eec7cf11597267de780299d0d.json deleted file mode 100644 index 4b85000..0000000 Binary files a/.sqlx/query-3fe383ea9ed4965e25d54eea08fb5abbab1b0c8eec7cf11597267de780299d0d.json and /dev/null differ diff --git a/.sqlx/query-457e9d4808332255ed7354a28e6ebc2015558f66dbcd00cb4ce559d80f2bd023.json b/.sqlx/query-457e9d4808332255ed7354a28e6ebc2015558f66dbcd00cb4ce559d80f2bd023.json deleted file mode 100644 index e40bb94..0000000 Binary files a/.sqlx/query-457e9d4808332255ed7354a28e6ebc2015558f66dbcd00cb4ce559d80f2bd023.json and /dev/null differ diff --git a/.sqlx/query-486ed307f718754a3d4ea2c6fe944f9571c88fad3316593edf0c72ddef24c73e.json b/.sqlx/query-486ed307f718754a3d4ea2c6fe944f9571c88fad3316593edf0c72ddef24c73e.json deleted file mode 100644 index a4bfa26..0000000 Binary files a/.sqlx/query-486ed307f718754a3d4ea2c6fe944f9571c88fad3316593edf0c72ddef24c73e.json and /dev/null differ diff --git a/.sqlx/query-49afbeaa1d32f8c2e6fea7a2d57a11ec04dd0aab26139c19583af00e5baaba56.json b/.sqlx/query-49afbeaa1d32f8c2e6fea7a2d57a11ec04dd0aab26139c19583af00e5baaba56.json deleted file mode 100644 index 90e1cca..0000000 Binary files a/.sqlx/query-49afbeaa1d32f8c2e6fea7a2d57a11ec04dd0aab26139c19583af00e5baaba56.json and /dev/null differ diff --git a/.sqlx/query-4f5408e64f5e6a8dd923c3b147f993ce9e4cafc90204b06977481130ec06d111.json b/.sqlx/query-4f5408e64f5e6a8dd923c3b147f993ce9e4cafc90204b06977481130ec06d111.json deleted file mode 100644 index 78e4867..0000000 Binary files a/.sqlx/query-4f5408e64f5e6a8dd923c3b147f993ce9e4cafc90204b06977481130ec06d111.json and /dev/null differ diff --git a/.sqlx/query-52958684fa52b7a4753cd4356482dc6c655102a501d8aa48e03b1fb3dbbad02d.json b/.sqlx/query-52958684fa52b7a4753cd4356482dc6c655102a501d8aa48e03b1fb3dbbad02d.json deleted file mode 100644 index 63080c4..0000000 Binary files a/.sqlx/query-52958684fa52b7a4753cd4356482dc6c655102a501d8aa48e03b1fb3dbbad02d.json and /dev/null differ diff --git a/.sqlx/query-5865f27b97487b6dfd956a3d260b9bbb0e6c203b721d29cf9149f60bfdd93465.json b/.sqlx/query-5865f27b97487b6dfd956a3d260b9bbb0e6c203b721d29cf9149f60bfdd93465.json deleted file mode 100644 index 67ea7e8..0000000 Binary files a/.sqlx/query-5865f27b97487b6dfd956a3d260b9bbb0e6c203b721d29cf9149f60bfdd93465.json and /dev/null differ diff --git a/.sqlx/query-66a141b71041a7827f1932e6e288fdab37cc699720e5484c30697b5566b8d513.json b/.sqlx/query-66a141b71041a7827f1932e6e288fdab37cc699720e5484c30697b5566b8d513.json deleted file mode 100644 index c08e9fc..0000000 Binary files a/.sqlx/query-66a141b71041a7827f1932e6e288fdab37cc699720e5484c30697b5566b8d513.json and /dev/null differ diff --git a/.sqlx/query-711398eb64710a25cc818167be8f3b2d03cab39116c2732c06e3c74a02fb0367.json b/.sqlx/query-711398eb64710a25cc818167be8f3b2d03cab39116c2732c06e3c74a02fb0367.json deleted file mode 100644 index 4409006..0000000 Binary files a/.sqlx/query-711398eb64710a25cc818167be8f3b2d03cab39116c2732c06e3c74a02fb0367.json and /dev/null differ diff --git a/.sqlx/query-7519da166e2e0b6de4c02559fc173396e85db762d482607e4662e788c5542fea.json b/.sqlx/query-7519da166e2e0b6de4c02559fc173396e85db762d482607e4662e788c5542fea.json deleted file mode 100644 index 2640d90..0000000 Binary files a/.sqlx/query-7519da166e2e0b6de4c02559fc173396e85db762d482607e4662e788c5542fea.json and /dev/null differ diff --git a/.sqlx/query-772c710d542c7f5aaa49069fe12a7a37ef509f50954509557ec985c996960da2.json b/.sqlx/query-772c710d542c7f5aaa49069fe12a7a37ef509f50954509557ec985c996960da2.json deleted file mode 100644 index 6915ce7..0000000 Binary files a/.sqlx/query-772c710d542c7f5aaa49069fe12a7a37ef509f50954509557ec985c996960da2.json and /dev/null differ diff --git a/.sqlx/query-7b3ee1cad84a146699b9010be6d31665a416687772b95d159e5d3e98cde3511c.json b/.sqlx/query-7b3ee1cad84a146699b9010be6d31665a416687772b95d159e5d3e98cde3511c.json deleted file mode 100644 index c904161..0000000 Binary files a/.sqlx/query-7b3ee1cad84a146699b9010be6d31665a416687772b95d159e5d3e98cde3511c.json and /dev/null differ diff --git a/.sqlx/query-7bbe1a982c77194feba2ff610b01e824b99a3888adf5365619ecfed7ae6544a9.json b/.sqlx/query-7bbe1a982c77194feba2ff610b01e824b99a3888adf5365619ecfed7ae6544a9.json deleted file mode 100644 index 217c70f..0000000 Binary files a/.sqlx/query-7bbe1a982c77194feba2ff610b01e824b99a3888adf5365619ecfed7ae6544a9.json and /dev/null differ diff --git a/.sqlx/query-7cd5b42013b4e6a37a670e55cd3ceb0911001eee41256f7b324edc72f5cadcba.json b/.sqlx/query-7cd5b42013b4e6a37a670e55cd3ceb0911001eee41256f7b324edc72f5cadcba.json deleted file mode 100644 index 8d846ef..0000000 Binary files a/.sqlx/query-7cd5b42013b4e6a37a670e55cd3ceb0911001eee41256f7b324edc72f5cadcba.json and /dev/null differ diff --git a/.sqlx/query-7e7cdf2650c08feb10a35275e693d0d3c690b4e9bccc6f0f5fed2bfd2826b480.json b/.sqlx/query-7e7cdf2650c08feb10a35275e693d0d3c690b4e9bccc6f0f5fed2bfd2826b480.json deleted file mode 100644 index c9df19d..0000000 Binary files a/.sqlx/query-7e7cdf2650c08feb10a35275e693d0d3c690b4e9bccc6f0f5fed2bfd2826b480.json and /dev/null differ diff --git a/.sqlx/query-87b7396fb761030e25836cb90ed07a1bdaa1d82ae3d43d107cf8bac3e9ba4c25.json b/.sqlx/query-87b7396fb761030e25836cb90ed07a1bdaa1d82ae3d43d107cf8bac3e9ba4c25.json deleted file mode 100644 index 63d4cfd..0000000 Binary files a/.sqlx/query-87b7396fb761030e25836cb90ed07a1bdaa1d82ae3d43d107cf8bac3e9ba4c25.json and /dev/null differ diff --git a/.sqlx/query-8bdd41a11fd2ca0440b2d6c0dc752a342012048741bdcd1ff9461bc46e1cf701.json b/.sqlx/query-8bdd41a11fd2ca0440b2d6c0dc752a342012048741bdcd1ff9461bc46e1cf701.json deleted file mode 100644 index 39b331c..0000000 Binary files a/.sqlx/query-8bdd41a11fd2ca0440b2d6c0dc752a342012048741bdcd1ff9461bc46e1cf701.json and /dev/null differ diff --git a/.sqlx/query-90ed2cd2f8161552dae06ab2d9cfee8914e253db00e6a648a78e99ade6a4de60.json b/.sqlx/query-90ed2cd2f8161552dae06ab2d9cfee8914e253db00e6a648a78e99ade6a4de60.json deleted file mode 100644 index 9be1170..0000000 Binary files a/.sqlx/query-90ed2cd2f8161552dae06ab2d9cfee8914e253db00e6a648a78e99ade6a4de60.json and /dev/null differ diff --git a/.sqlx/query-921a0775f75d9e2f67f604265872bf715af1e1ed4d420ac6fa132a94ff352e56.json b/.sqlx/query-921a0775f75d9e2f67f604265872bf715af1e1ed4d420ac6fa132a94ff352e56.json deleted file mode 100644 index a7c8c1e..0000000 Binary files a/.sqlx/query-921a0775f75d9e2f67f604265872bf715af1e1ed4d420ac6fa132a94ff352e56.json and /dev/null differ diff --git a/.sqlx/query-96a0b9960daa8a10e04e22cba592870941545b095193612956c29d37a5a1b774.json b/.sqlx/query-96a0b9960daa8a10e04e22cba592870941545b095193612956c29d37a5a1b774.json deleted file mode 100644 index c86b729..0000000 Binary files a/.sqlx/query-96a0b9960daa8a10e04e22cba592870941545b095193612956c29d37a5a1b774.json and /dev/null differ diff --git a/.sqlx/query-96f34b8654265ea5ab5210ab5dcad8c0bacd8d9e73e375dc35e759bdb82369a1.json b/.sqlx/query-96f34b8654265ea5ab5210ab5dcad8c0bacd8d9e73e375dc35e759bdb82369a1.json deleted file mode 100644 index 705a3b0..0000000 Binary files a/.sqlx/query-96f34b8654265ea5ab5210ab5dcad8c0bacd8d9e73e375dc35e759bdb82369a1.json and /dev/null differ diff --git a/.sqlx/query-a0c9c1a108c6560b4f073c866415a94af2e823a8d88ab2aa5ace8c2b56023004.json b/.sqlx/query-a0c9c1a108c6560b4f073c866415a94af2e823a8d88ab2aa5ace8c2b56023004.json deleted file mode 100644 index ead136f..0000000 Binary files a/.sqlx/query-a0c9c1a108c6560b4f073c866415a94af2e823a8d88ab2aa5ace8c2b56023004.json and /dev/null differ diff --git a/.sqlx/query-a1f5699889cfabb3f681e6bb71a8d7c739d0cb82eea1f8289d012c37bd30c776.json b/.sqlx/query-a1f5699889cfabb3f681e6bb71a8d7c739d0cb82eea1f8289d012c37bd30c776.json deleted file mode 100644 index 2dfa516..0000000 Binary files a/.sqlx/query-a1f5699889cfabb3f681e6bb71a8d7c739d0cb82eea1f8289d012c37bd30c776.json and /dev/null differ diff --git a/.sqlx/query-a64694ec1a81472a05a68b1caf64c32a261bb7d1f34577c0f4dc52e318124ecd.json b/.sqlx/query-a64694ec1a81472a05a68b1caf64c32a261bb7d1f34577c0f4dc52e318124ecd.json deleted file mode 100644 index cd86c5f..0000000 Binary files a/.sqlx/query-a64694ec1a81472a05a68b1caf64c32a261bb7d1f34577c0f4dc52e318124ecd.json and /dev/null differ diff --git a/.sqlx/query-a69f0bf9b3fefd7914502aa15fa120ecf4e5542011b781d8023bdb422580d97a.json b/.sqlx/query-a69f0bf9b3fefd7914502aa15fa120ecf4e5542011b781d8023bdb422580d97a.json deleted file mode 100644 index f6c5009..0000000 Binary files a/.sqlx/query-a69f0bf9b3fefd7914502aa15fa120ecf4e5542011b781d8023bdb422580d97a.json and /dev/null differ diff --git a/.sqlx/query-a6dc153657cb3fefb5ba5b763dc5b7b4da78ab8acec79c7e7ea51ce5c9414bcb.json b/.sqlx/query-a6dc153657cb3fefb5ba5b763dc5b7b4da78ab8acec79c7e7ea51ce5c9414bcb.json deleted file mode 100644 index a0e8505..0000000 Binary files a/.sqlx/query-a6dc153657cb3fefb5ba5b763dc5b7b4da78ab8acec79c7e7ea51ce5c9414bcb.json and /dev/null differ diff --git a/.sqlx/query-a8b2d9cfd386b5f9ad5b76ef08711691dae057a431fffc27417e4f5504dcfb30.json b/.sqlx/query-a8b2d9cfd386b5f9ad5b76ef08711691dae057a431fffc27417e4f5504dcfb30.json deleted file mode 100644 index bd4f9f7..0000000 Binary files a/.sqlx/query-a8b2d9cfd386b5f9ad5b76ef08711691dae057a431fffc27417e4f5504dcfb30.json and /dev/null differ diff --git a/.sqlx/query-a94cb95af7e6c13e0e155c74de2febe44c1250f25989034a3f9e4e8bcb39dece.json b/.sqlx/query-a94cb95af7e6c13e0e155c74de2febe44c1250f25989034a3f9e4e8bcb39dece.json deleted file mode 100644 index b203d50..0000000 Binary files a/.sqlx/query-a94cb95af7e6c13e0e155c74de2febe44c1250f25989034a3f9e4e8bcb39dece.json and /dev/null differ diff --git a/.sqlx/query-ab8dafa95af67dc06074e83e1ec61be2fe713637f883d175f9b279f0f2f8fd87.json b/.sqlx/query-ab8dafa95af67dc06074e83e1ec61be2fe713637f883d175f9b279f0f2f8fd87.json deleted file mode 100644 index 24cf02e..0000000 Binary files a/.sqlx/query-ab8dafa95af67dc06074e83e1ec61be2fe713637f883d175f9b279f0f2f8fd87.json and /dev/null differ diff --git a/.sqlx/query-b41855e635ac409559fa63cba4c1285034c573b86e3193da3995606dee412153.json b/.sqlx/query-b41855e635ac409559fa63cba4c1285034c573b86e3193da3995606dee412153.json deleted file mode 100644 index 94419bd..0000000 Binary files a/.sqlx/query-b41855e635ac409559fa63cba4c1285034c573b86e3193da3995606dee412153.json and /dev/null differ diff --git a/.sqlx/query-b6f6fd898dc3f1dbe2c39bf0445bac76c8233c0feee15f4504bf74ea864716ce.json b/.sqlx/query-b6f6fd898dc3f1dbe2c39bf0445bac76c8233c0feee15f4504bf74ea864716ce.json deleted file mode 100644 index 611b0de..0000000 Binary files a/.sqlx/query-b6f6fd898dc3f1dbe2c39bf0445bac76c8233c0feee15f4504bf74ea864716ce.json and /dev/null differ diff --git a/.sqlx/query-b91f6aab0bdb316633b3a0d75303086dd6e4e204e9e063535b19db666476fe88.json b/.sqlx/query-b91f6aab0bdb316633b3a0d75303086dd6e4e204e9e063535b19db666476fe88.json deleted file mode 100644 index 24b6a13..0000000 Binary files a/.sqlx/query-b91f6aab0bdb316633b3a0d75303086dd6e4e204e9e063535b19db666476fe88.json and /dev/null differ diff --git a/.sqlx/query-bcd9d4dd3641e6c84262ed5f6c5646f825be186da276b113c0150aaad26b057c.json b/.sqlx/query-bcd9d4dd3641e6c84262ed5f6c5646f825be186da276b113c0150aaad26b057c.json deleted file mode 100644 index b312064..0000000 Binary files a/.sqlx/query-bcd9d4dd3641e6c84262ed5f6c5646f825be186da276b113c0150aaad26b057c.json and /dev/null differ diff --git a/.sqlx/query-c138a9c659a7410e9935ad3f6a56c2bc73174fb1921fe1260702f1eab87d979c.json b/.sqlx/query-c138a9c659a7410e9935ad3f6a56c2bc73174fb1921fe1260702f1eab87d979c.json deleted file mode 100644 index 6518f69..0000000 Binary files a/.sqlx/query-c138a9c659a7410e9935ad3f6a56c2bc73174fb1921fe1260702f1eab87d979c.json and /dev/null differ diff --git a/.sqlx/query-c30156fb112fcc28f08fbbec04197c41c9f71f6a4a3f44221f5ec012c99ebf54.json b/.sqlx/query-c30156fb112fcc28f08fbbec04197c41c9f71f6a4a3f44221f5ec012c99ebf54.json deleted file mode 100644 index 9d225d6..0000000 Binary files a/.sqlx/query-c30156fb112fcc28f08fbbec04197c41c9f71f6a4a3f44221f5ec012c99ebf54.json and /dev/null differ diff --git a/.sqlx/query-c9437ff0c3014b269dcb21304fbad12237b9cb69ea6aa4686df6d5262065faa2.json b/.sqlx/query-c9437ff0c3014b269dcb21304fbad12237b9cb69ea6aa4686df6d5262065faa2.json deleted file mode 100644 index 10fe1a3..0000000 Binary files a/.sqlx/query-c9437ff0c3014b269dcb21304fbad12237b9cb69ea6aa4686df6d5262065faa2.json and /dev/null differ diff --git a/.sqlx/query-cb0d76a3a1cfa439d48056c865cd5bfbfbc785fa795254120822b843ce63ff07.json b/.sqlx/query-cb0d76a3a1cfa439d48056c865cd5bfbfbc785fa795254120822b843ce63ff07.json deleted file mode 100644 index 0626f8d..0000000 Binary files a/.sqlx/query-cb0d76a3a1cfa439d48056c865cd5bfbfbc785fa795254120822b843ce63ff07.json and /dev/null differ diff --git a/.sqlx/query-cbda6fd5137f3698537262772df22a0a66064e3416e4f5c89d8d83fa6c0536ad.json b/.sqlx/query-cbda6fd5137f3698537262772df22a0a66064e3416e4f5c89d8d83fa6c0536ad.json deleted file mode 100644 index fb83516..0000000 Binary files a/.sqlx/query-cbda6fd5137f3698537262772df22a0a66064e3416e4f5c89d8d83fa6c0536ad.json and /dev/null differ diff --git a/.sqlx/query-cdcae4768f7b62390e5e5da850e301b502ffd56dd88485cd73b694f6559ccd4e.json b/.sqlx/query-cdcae4768f7b62390e5e5da850e301b502ffd56dd88485cd73b694f6559ccd4e.json deleted file mode 100644 index 97b4b65..0000000 Binary files a/.sqlx/query-cdcae4768f7b62390e5e5da850e301b502ffd56dd88485cd73b694f6559ccd4e.json and /dev/null differ diff --git a/.sqlx/query-db48fb93e9f22ee7da0786ae913d962b1da35b5b2b663f759f6af106650951b8.json b/.sqlx/query-db48fb93e9f22ee7da0786ae913d962b1da35b5b2b663f759f6af106650951b8.json deleted file mode 100644 index f31d95b..0000000 Binary files a/.sqlx/query-db48fb93e9f22ee7da0786ae913d962b1da35b5b2b663f759f6af106650951b8.json and /dev/null differ diff --git a/.sqlx/query-e9386ab7ecbe4ce13f8ee5ee5852697741fb210ea8bfc3d61f1508106c0b076e.json b/.sqlx/query-e9386ab7ecbe4ce13f8ee5ee5852697741fb210ea8bfc3d61f1508106c0b076e.json deleted file mode 100644 index e54e4a6..0000000 Binary files a/.sqlx/query-e9386ab7ecbe4ce13f8ee5ee5852697741fb210ea8bfc3d61f1508106c0b076e.json and /dev/null differ diff --git a/.sqlx/query-e94ef5bc8b267d493375bb371dcfb7b09f6355ecbc8b6e1085d5f2f9a08cac3f.json b/.sqlx/query-e94ef5bc8b267d493375bb371dcfb7b09f6355ecbc8b6e1085d5f2f9a08cac3f.json deleted file mode 100644 index 391ca72..0000000 Binary files a/.sqlx/query-e94ef5bc8b267d493375bb371dcfb7b09f6355ecbc8b6e1085d5f2f9a08cac3f.json and /dev/null differ diff --git a/.sqlx/query-ea4b06aaad9436096e20a53d81fd36ed21da18ceed5b71e51a1e749bab466422.json b/.sqlx/query-ea4b06aaad9436096e20a53d81fd36ed21da18ceed5b71e51a1e749bab466422.json deleted file mode 100644 index 1967a26..0000000 Binary files a/.sqlx/query-ea4b06aaad9436096e20a53d81fd36ed21da18ceed5b71e51a1e749bab466422.json and /dev/null differ diff --git a/.sqlx/query-ee7da56331bece2efe21b55dbd5f420d3abb08358a1abe301dc7e08693fbef4d.json b/.sqlx/query-ee7da56331bece2efe21b55dbd5f420d3abb08358a1abe301dc7e08693fbef4d.json deleted file mode 100644 index c4ec08d..0000000 Binary files a/.sqlx/query-ee7da56331bece2efe21b55dbd5f420d3abb08358a1abe301dc7e08693fbef4d.json and /dev/null differ diff --git a/.sqlx/query-eee8820f59927c1560a5fd461b9f4a2d40abdf3843d0c815399ea9d267cade5a.json b/.sqlx/query-eee8820f59927c1560a5fd461b9f4a2d40abdf3843d0c815399ea9d267cade5a.json deleted file mode 100644 index cb7c1bd..0000000 Binary files a/.sqlx/query-eee8820f59927c1560a5fd461b9f4a2d40abdf3843d0c815399ea9d267cade5a.json and /dev/null differ diff --git a/.sqlx/query-f75318134ec1facc3de6b04232cb28a92524b8f556840b76f76c8f317059e668.json b/.sqlx/query-f75318134ec1facc3de6b04232cb28a92524b8f556840b76f76c8f317059e668.json deleted file mode 100644 index 88dc7d1..0000000 Binary files a/.sqlx/query-f75318134ec1facc3de6b04232cb28a92524b8f556840b76f76c8f317059e668.json and /dev/null differ diff --git a/.sqlx/query-f7b90a6a0af3f7d7c96158f96f1ada06827a0e5a2d2dbd48bfb8e04f973a6131.json b/.sqlx/query-f7b90a6a0af3f7d7c96158f96f1ada06827a0e5a2d2dbd48bfb8e04f973a6131.json deleted file mode 100644 index caa30a4..0000000 Binary files a/.sqlx/query-f7b90a6a0af3f7d7c96158f96f1ada06827a0e5a2d2dbd48bfb8e04f973a6131.json and /dev/null differ diff --git a/.sqlx/query-fde0dca1aba5b490a9f5f6006677be750a7bcf5d1185935e8386671c69dc7270.json b/.sqlx/query-fde0dca1aba5b490a9f5f6006677be750a7bcf5d1185935e8386671c69dc7270.json deleted file mode 100644 index 8d164fb..0000000 Binary files a/.sqlx/query-fde0dca1aba5b490a9f5f6006677be750a7bcf5d1185935e8386671c69dc7270.json and /dev/null differ diff --git a/Cargo.toml b/Cargo.toml index 92bf0a0..db76e00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,31 @@ -[workspace] -resolver = "2" -members = [ - "emgauwa-core", - "emgauwa-controller", - "emgauwa-common", -] +[package] +name = "emgauwa-core" +version = "0.5.0" +edition = "2021" +authors = ["Tobias Reisinger "] + +[dependencies] +emgauwa-common = { git = "https://git.serguzim.me/emgauwa/common.git" } + +actix = "0.13" +actix-web = "4.4" +actix-web-actors = "4.2" +actix-cors = "0.7" + +utoipa = "4.2" +utoipa-swagger-ui = { version = "6.0", features = ["actix-web", "debug-embed"] } + +log = "0.4" + +chrono = { version = "0.4", features = ["serde"] } +uuid = { version = "1.5", features = ["serde", "v4"] } +itertools = "0.12" + +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" + +sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio", "macros", "chrono"] } + +futures = "0.3" +tokio = { version = "1.36", features = ["rt", "rt-multi-thread"] } diff --git a/Makefile b/Makefile index 7c49652..8d69e1e 100644 --- a/Makefile +++ b/Makefile @@ -1,42 +1,23 @@ -sqlx: - cargo sqlx database drop -y - cargo sqlx database create - cargo sqlx migrate run - cargo sqlx prepare --workspace - build-rpi: cross build --target arm-unknown-linux-gnueabihf -emgauwa-%.json: config/%.pkl +emgauwa-core.json: core.pkl pkl eval -f json -o $@ $< -configs: +config: $(MAKE) emgauwa-core.json - $(MAKE) emgauwa-controller.json clean: - rm -f emgauwa-controller.json - rm -f emgauwa-controller.sqlite rm -f emgauwa-core.json rm -f emgauwa-core.sqlite - rm -f emgauwa-dev.sqlite - -emgauwa-controller_%: - $(TOOL) build --target $* --release --bin emgauwa-controller - mkdir -p out/releases - cp target/$*/release/emgauwa-controller out/releases/emgauwa-controller_$* emgauwa-core_%: $(TOOL) build --target $* --release --bin emgauwa-core mkdir -p out/releases cp target/$*/release/emgauwa-core out/releases/emgauwa-core_$* -emgauwa_%: - $(MAKE) emgauwa-controller_$* - $(MAKE) emgauwa-core_$* - releases: - $(MAKE) TOOL=cross emgauwa_arm-unknown-linux-gnueabihf - $(MAKE) TOOL=cargo emgauwa_x86_64-unknown-linux-gnu - $(MAKE) TOOL=cross emgauwa_x86_64-unknown-linux-musl + $(MAKE) TOOL=cross emgauwa-core_arm-unknown-linux-gnueabihf + $(MAKE) TOOL=cargo emgauwa-core_x86_64-unknown-linux-gnu + $(MAKE) TOOL=cross emgauwa-core_x86_64-unknown-linux-musl diff --git a/emgauwa-core/build.rs b/build.rs similarity index 72% rename from emgauwa-core/build.rs rename to build.rs index 27e067f..cfdf256 100644 --- a/emgauwa-core/build.rs +++ b/build.rs @@ -1,10 +1,10 @@ use std::process::{exit, Command}; fn main() { - println!("cargo:rerun-if-changed=../api.v1.yaml"); + println!("cargo:rerun-if-changed=./api.v1.yaml"); let output = Command::new("sh") .arg("-c") - .arg("yq . < ../api.v1.yaml > $OUT_DIR/api.v1.json") + .arg("yq . < ./api.v1.yaml > $OUT_DIR/api.v1.json") .output() .expect("Failed to convert api documentation to json"); diff --git a/config/controller.pkl b/config/controller.pkl deleted file mode 100644 index 11e735e..0000000 --- a/config/controller.pkl +++ /dev/null @@ -1,56 +0,0 @@ -amends "package://emgauwa.app/pkl/emgauwa@0.1.0#/controller.pkl" - -relays { - new { - driver = "null" - pin = 0 - inverted = true - } - new { - driver = "null" - pin = 1 - inverted = true - } - new { - driver = "null" - pin = 2 - inverted = true - } - new { - driver = "null" - pin = 3 - inverted = true - } - new { - driver = "null" - pin = 4 - inverted = true - } - new { - driver = "null" - pin = 5 - inverted = true - } - new { - driver = "null" - pin = 10 - inverted = true - pulse = 10 - } - new { - driver = "null" - pin = 11 - inverted = true - pulse = 10 - } - new { - driver = "null" - pin = 20 - inverted = false - } - new { - driver = "null" - pin = 21 - inverted = false - } -} \ No newline at end of file diff --git a/config/core.pkl b/core.pkl similarity index 100% rename from config/core.pkl rename to core.pkl diff --git a/emgauwa-common/Cargo.toml b/emgauwa-common/Cargo.toml deleted file mode 100644 index e11518a..0000000 --- a/emgauwa-common/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "emgauwa-common" -version = "0.5.0" -edition = "2021" -authors = ["Tobias Reisinger "] - - -[dependencies] -actix = "0.13" -actix-web = "4.4" -actix-web-actors = "4.2" - -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" - -simple_logger = "4.2" -log = "0.4" - -config = "0.13" - -chrono = { version = "0.4", features = ["serde"] } - -sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio", "macros", "chrono"] } -libsqlite3-sys = { version = "*", features = ["bundled"] } -uuid = "1.6" -futures = "0.3" -libc = "0.2" - -rppal = "0.17" -rppal-pfd = "0.0.5" -rppal-mcp23s17 = "0.0.3" diff --git a/emgauwa-common/build.rs b/emgauwa-common/build.rs deleted file mode 100644 index 827c260..0000000 --- a/emgauwa-common/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=migrations"); -} diff --git a/emgauwa-common/src/constants.rs b/emgauwa-common/src/constants.rs deleted file mode 100644 index 92874a2..0000000 --- a/emgauwa-common/src/constants.rs +++ /dev/null @@ -1,10 +0,0 @@ -use std::time::Duration; - -pub const DEFAULT_PORT: u16 = 4419; -pub const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); -pub const HEARTBEAT_TIMEOUT: Duration = Duration::from_secs(15); - -pub const WEBSOCKET_RETRY_TIMEOUT: Duration = Duration::from_secs(5); -pub const RELAYS_RETRY_TIMEOUT: Duration = Duration::from_secs(5); - -pub const RELAY_PULSE_DURATION: u64 = 3; diff --git a/emgauwa-common/src/db/controllers.rs b/emgauwa-common/src/db/controllers.rs deleted file mode 100644 index bf0a1f0..0000000 --- a/emgauwa-common/src/db/controllers.rs +++ /dev/null @@ -1,184 +0,0 @@ -use std::ops::DerefMut; - -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbRelay, DbTag}; -use crate::errors::DatabaseError; -use crate::types::EmgauwaUid; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DbController { - #[serde(skip)] - pub id: i64, - #[serde(rename = "id")] - pub uid: EmgauwaUid, - pub name: String, - pub relay_count: i64, - pub active: bool, -} - -impl DbController { - pub async fn get_all( - conn: &mut PoolConnection, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbController, "SELECT * FROM controllers") - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get( - conn: &mut PoolConnection, - id: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbController, "SELECT * FROM controllers WHERE id = ?", id) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_uid( - conn: &mut PoolConnection, - filter_uid: &EmgauwaUid, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbController, - "SELECT * FROM controllers WHERE uid = ?", - filter_uid - ) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_uid_or_create( - conn: &mut PoolConnection, - uid: &EmgauwaUid, - new_name: &str, - new_relay_count: i64, - ) -> Result { - match DbController::get_by_uid(conn, uid).await? { - Some(tag) => Ok(tag), - None => DbController::create(conn, uid, new_name, new_relay_count).await, - } - } - - pub async fn get_by_tag( - conn: &mut PoolConnection, - tag: &DbTag, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbController, "SELECT schedule.* FROM controllers AS schedule INNER JOIN junction_tag ON junction_tag.schedule_id = schedule.id WHERE junction_tag.tag_id = ?", tag.id) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn delete_by_uid( - conn: &mut PoolConnection, - filter_uid: EmgauwaUid, - ) -> Result<(), DatabaseError> { - if sqlx::query_scalar!("SELECT 1 FROM controllers WHERE uid = ?", filter_uid) - .fetch_optional(conn.deref_mut()) - .await? - .is_none() - { - return Err(DatabaseError::NotFound); - } - - sqlx::query!("DELETE FROM controllers WHERE uid = ?", filter_uid) - .execute(conn.deref_mut()) - .await - .map(|res| match res.rows_affected() { - 0 => Err(DatabaseError::DeleteError), - _ => Ok(()), - })? - } - - pub async fn create( - conn: &mut PoolConnection, - new_uid: &EmgauwaUid, - new_name: &str, - new_relay_count: i64, - ) -> Result { - sqlx::query_as!( - DbController, - "INSERT INTO controllers (uid, name, relay_count) VALUES (?, ?, ?) RETURNING *", - new_uid, - new_name, - new_relay_count, - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } - - pub async fn update( - &self, - conn: &mut PoolConnection, - new_name: &str, - new_relay_count: i64, - ) -> Result { - sqlx::query!( - "UPDATE controllers SET name = ?, relay_count = ? WHERE id = ?", - new_name, - new_relay_count, - self.id, - ) - .execute(conn.deref_mut()) - .await?; - - Self::get(conn, self.id) - .await? - .ok_or(DatabaseError::UpdateGetError) - } - - pub async fn update_active( - &self, - conn: &mut PoolConnection, - new_active: bool, - ) -> Result { - sqlx::query!( - "UPDATE controllers SET active = ? WHERE id = ?", - new_active, - self.id, - ) - .execute(conn.deref_mut()) - .await?; - - Self::get(conn, self.id) - .await? - .ok_or(DatabaseError::UpdateGetError) - } - - pub async fn get_relays( - &self, - conn: &mut PoolConnection, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbRelay, - "SELECT * FROM relays WHERE controller_id = ?", - self.id - ) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn all_inactive(conn: &mut PoolConnection) -> Result<(), DatabaseError> { - sqlx::query!("UPDATE controllers SET active = 0") - .execute(conn.deref_mut()) - .await?; - Ok(()) - } - - pub async fn reload( - &self, - conn: &mut PoolConnection, - ) -> Result { - Self::get(conn, self.id) - .await? - .ok_or(DatabaseError::NotFound) - } -} diff --git a/emgauwa-common/src/db/junction_relay_schedule.rs b/emgauwa-common/src/db/junction_relay_schedule.rs deleted file mode 100644 index f081a54..0000000 --- a/emgauwa-common/src/db/junction_relay_schedule.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::ops::DerefMut; - -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbRelay, DbSchedule}; -use crate::errors::DatabaseError; -use crate::types::Weekday; - -pub struct DbJunctionRelaySchedule { - pub id: i64, - pub weekday: Weekday, - pub relay_id: i64, - pub schedule_id: i64, -} - -impl DbJunctionRelaySchedule { - pub async fn get( - conn: &mut PoolConnection, - id: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbJunctionRelaySchedule, - "SELECT * FROM junction_relay_schedule WHERE id = ?", - id - ) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_junction_by_relay_and_weekday( - conn: &mut PoolConnection, - relay: &DbRelay, - weekday: Weekday, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbJunctionRelaySchedule, - "SELECT * FROM junction_relay_schedule WHERE relay_id = ? AND weekday = ?", - relay.id, - weekday - ) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_relays( - conn: &mut PoolConnection, - schedule: &DbSchedule, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbRelay, - r#"SELECT relays.* FROM relays INNER JOIN junction_relay_schedule - ON junction_relay_schedule.relay_id = relays.id - WHERE junction_relay_schedule.schedule_id = ? - ORDER BY junction_relay_schedule.weekday"#, - schedule.id - ) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_schedule( - conn: &mut PoolConnection, - relay: &DbRelay, - weekday: Weekday, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbSchedule, - r#"SELECT schedules.* FROM schedules INNER JOIN junction_relay_schedule - ON junction_relay_schedule.schedule_id = schedules.id - WHERE junction_relay_schedule.relay_id = ? AND junction_relay_schedule.weekday = ?"#, - relay.id, - weekday - ) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_schedules( - conn: &mut PoolConnection, - relay: &DbRelay, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbSchedule, - r#"SELECT schedules.* FROM schedules INNER JOIN junction_relay_schedule - ON junction_relay_schedule.schedule_id = schedules.id - WHERE junction_relay_schedule.relay_id = ? - ORDER BY junction_relay_schedule.weekday"#, - relay.id - ) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn set_schedule( - conn: &mut PoolConnection, - relay: &DbRelay, - schedule: &DbSchedule, - weekday: Weekday, - ) -> Result { - match Self::get_junction_by_relay_and_weekday(conn, relay, weekday).await? { - None => sqlx::query_as!( - DbJunctionRelaySchedule, - "INSERT INTO junction_relay_schedule (weekday, relay_id, schedule_id) VALUES (?, ?, ?) RETURNING *", - weekday, - relay.id, - schedule.id - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError), - - Some(junction) => { - sqlx::query!( - "UPDATE junction_relay_schedule SET weekday = ?, relay_id = ?, schedule_id= ? WHERE id = ?", - weekday, - relay.id, - schedule.id, - junction.id - ) - .execute(conn.deref_mut()) - .await?; - - Self::get(conn, junction.id) - .await? - .ok_or(DatabaseError::UpdateGetError) - } - } - } - - pub async fn set_schedules( - conn: &mut PoolConnection, - relay: &DbRelay, - schedules: Vec<&DbSchedule>, - ) -> Result<(), DatabaseError> { - for (weekday, schedule) in schedules.iter().enumerate() { - Self::set_schedule(conn, relay, schedule, weekday as Weekday).await?; - } - Ok(()) - } -} diff --git a/emgauwa-common/src/db/junction_tag.rs b/emgauwa-common/src/db/junction_tag.rs deleted file mode 100644 index f1b8816..0000000 --- a/emgauwa-common/src/db/junction_tag.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::ops::DerefMut; - -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbRelay, DbSchedule, DbTag}; -use crate::errors::DatabaseError; - -pub struct DbJunctionTag { - pub id: i64, - pub tag_id: i64, - pub relay_id: Option, - pub schedule_id: Option, -} - -impl DbJunctionTag { - pub async fn link_relay( - conn: &mut PoolConnection, - tag: &DbTag, - relay: &DbRelay, - ) -> Result { - sqlx::query_as!( - DbJunctionTag, - "INSERT INTO junction_tag (tag_id, relay_id) VALUES (?, ?) RETURNING *", - tag.id, - relay.id - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } - - pub async fn link_schedule( - conn: &mut PoolConnection, - tag: &DbTag, - schedule: &DbSchedule, - ) -> Result { - sqlx::query_as!( - DbJunctionTag, - "INSERT INTO junction_tag (tag_id, schedule_id) VALUES (?, ?) RETURNING *", - tag.id, - schedule.id - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } -} diff --git a/emgauwa-common/src/db/macro.rs b/emgauwa-common/src/db/macro.rs deleted file mode 100644 index 1ced624..0000000 --- a/emgauwa-common/src/db/macro.rs +++ /dev/null @@ -1,166 +0,0 @@ -use std::ops::DerefMut; - -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbController, DbMacroAction, DbRelay, DbSchedule}; -use crate::errors::DatabaseError; -use crate::types::{EmgauwaUid, RequestMacroAction}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DbMacro { - #[serde(skip)] - pub id: i64, - #[serde(rename = "id")] - pub uid: EmgauwaUid, - pub name: String, -} - - -impl DbMacro { - pub async fn get_all(conn: &mut PoolConnection) -> Result, DatabaseError> { - sqlx::query_as!(DbMacro, "SELECT * FROM macros") - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get( - conn: &mut PoolConnection, - id: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbMacro, "SELECT * FROM macros WHERE id = ?", id) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_uid( - conn: &mut PoolConnection, - filter_uid: &EmgauwaUid, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbMacro, "SELECT * FROM macros WHERE uid = ?", filter_uid) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn create( - conn: &mut PoolConnection, - new_uid: EmgauwaUid, - new_name: &str, - ) -> Result { - sqlx::query_as!( - DbMacro, - "INSERT INTO macros (uid, name) VALUES (?, ?) RETURNING *", - new_uid, - new_name - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } - - pub async fn delete(&self, conn: &mut PoolConnection) -> Result<(), DatabaseError> { - sqlx::query!("DELETE FROM macros WHERE id = ?", self.id) - .execute(conn.deref_mut()) - .await - .map(|res| match res.rows_affected() { - 0 => Err(DatabaseError::DeleteError), - _ => Ok(()), - })? - } - - pub async fn delete_by_uid( - conn: &mut PoolConnection, - filter_uid: EmgauwaUid, - ) -> Result<(), DatabaseError> { - if sqlx::query_scalar!("SELECT 1 FROM macros WHERE uid = ?", filter_uid) - .fetch_optional(conn.deref_mut()) - .await? - .is_none() - { - return Err(DatabaseError::NotFound); - } - - sqlx::query!("DELETE FROM macros WHERE uid = ?", filter_uid) - .execute(conn.deref_mut()) - .await - .map(|res| match res.rows_affected() { - 0 => Err(DatabaseError::DeleteError), - _ => Ok(()), - })? - } - - pub async fn update( - &self, - conn: &mut PoolConnection, - new_name: &str, - ) -> Result { - sqlx::query!("UPDATE relays SET name = ? WHERE id = ?", new_name, self.id,) - .execute(conn.deref_mut()) - .await?; - - DbMacro::get(conn, self.id) - .await? - .ok_or(DatabaseError::UpdateGetError) - } - - pub async fn set_actions( - &self, - conn: &mut PoolConnection, - new_actions: &[RequestMacroAction], - ) -> Result<(), DatabaseError> { - sqlx::query!("DELETE FROM macro_actions WHERE macro_id = ?", self.id) - .execute(conn.deref_mut()) - .await?; - - for new_action in new_actions { - let controller = DbController::get_by_uid(conn, &new_action.relay.controller_id) - .await? - .ok_or(DatabaseError::NotFound)?; - let relay = - DbRelay::get_by_controller_and_num(conn, &controller, new_action.relay.number) - .await? - .ok_or(DatabaseError::NotFound)?; - - let schedule = DbSchedule::get_by_uid(conn, &new_action.schedule.id) - .await? - .ok_or(DatabaseError::NotFound)?; - - DbMacroAction::create(conn, self, &relay, &schedule, new_action.weekday).await?; - } - Ok(()) - } - - pub async fn get_actions( - &self, - conn: &mut PoolConnection, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbMacroAction, - "SELECT * FROM macro_actions WHERE macro_id = ?", - self.id - ) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_actions_weekday( - &self, - conn: &mut PoolConnection, - weekday: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbMacroAction, - "SELECT * FROM macro_actions WHERE macro_id = ? AND weekday = ?", - self.id, - weekday - ) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } -} diff --git a/emgauwa-common/src/db/macro_action.rs b/emgauwa-common/src/db/macro_action.rs deleted file mode 100644 index 4a88c39..0000000 --- a/emgauwa-common/src/db/macro_action.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::ops::DerefMut; - -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbMacro, DbRelay, DbSchedule}; -use crate::errors::DatabaseError; - -#[derive(Debug, Clone)] -pub struct DbMacroAction { - pub id: i64, - pub macro_id: i64, - pub relay_id: i64, - pub schedule_id: i64, - pub weekday: i64, // should be u8, but sqlite will store it as i64 -} - - -impl DbMacroAction { - pub async fn get_all( - conn: &mut PoolConnection, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbMacroAction, "SELECT * FROM macro_actions") - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get( - conn: &mut PoolConnection, - id: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbMacroAction, - "SELECT * FROM macro_actions WHERE id = ?", - id - ) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn create( - conn: &mut PoolConnection, - new_macro: &DbMacro, - new_relay: &DbRelay, - new_schedule: &DbSchedule, - new_weekday: i64, - ) -> Result { - sqlx::query_as!( - DbMacroAction, - "INSERT INTO macro_actions (macro_id, relay_id, schedule_id, weekday) VALUES (?, ?, ?, ?) RETURNING *", - new_macro.id, - new_relay.id, - new_schedule.id, - new_weekday - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } - - pub async fn delete(&self, conn: &mut PoolConnection) -> Result<(), DatabaseError> { - sqlx::query!("DELETE FROM macro_actions WHERE id = ?", self.id) - .execute(conn.deref_mut()) - .await - .map(|res| match res.rows_affected() { - 0 => Err(DatabaseError::DeleteError), - _ => Ok(()), - })? - } - - pub async fn get_relay( - &self, - conn: &mut PoolConnection, - ) -> Result { - DbRelay::get(conn, self.relay_id) - .await? - .ok_or(DatabaseError::NotFound) - } - - pub async fn get_schedule( - &self, - conn: &mut PoolConnection, - ) -> Result { - DbSchedule::get(conn, self.schedule_id) - .await? - .ok_or(DatabaseError::NotFound) - } - - pub async fn get_macro( - &self, - conn: &mut PoolConnection, - ) -> Result { - DbMacro::get(conn, self.macro_id) - .await? - .ok_or(DatabaseError::NotFound) - } -} diff --git a/emgauwa-common/src/db/mod.rs b/emgauwa-common/src/db/mod.rs deleted file mode 100644 index c4f74b6..0000000 --- a/emgauwa-common/src/db/mod.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::str::FromStr; - -use sqlx::migrate::Migrator; -use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; -use sqlx::{ConnectOptions, Pool, Sqlite}; - -mod controllers; -mod junction_relay_schedule; -mod junction_tag; -mod r#macro; -mod macro_action; -mod model_utils; -mod relays; -mod schedules; -mod tag; - -pub use controllers::DbController; -pub use junction_relay_schedule::DbJunctionRelaySchedule; -pub use junction_tag::DbJunctionTag; -pub use macro_action::DbMacroAction; -pub use r#macro::DbMacro; -pub use relays::DbRelay; -pub use schedules::{DbPeriods, DbSchedule}; -pub use tag::DbTag; - -use crate::errors::{DatabaseError, EmgauwaError}; - -static MIGRATOR: Migrator = sqlx::migrate!("../migrations"); // defaults to "./migrations" - -pub async fn run_migrations(pool: &Pool) -> Result<(), EmgauwaError> { - log::info!("Running migrations"); - MIGRATOR.run(pool).await.map_err(DatabaseError::from)?; - Ok(()) -} - -pub async fn init(db: &str) -> Result, EmgauwaError> { - let options = SqliteConnectOptions::from_str(db)? - .create_if_missing(true) - .log_statements(log::LevelFilter::Trace); - - let pool: Pool = SqlitePoolOptions::new() - .acquire_timeout(std::time::Duration::from_secs(1)) - .max_connections(5) - .connect_with(options) - .await?; - - run_migrations(&pool).await?; - - let mut pool_conn = pool.acquire().await?; - - DbSchedule::get_on(&mut pool_conn).await?; - DbSchedule::get_off(&mut pool_conn).await?; - - Ok(pool) -} diff --git a/emgauwa-common/src/db/model_utils.rs b/emgauwa-common/src/db/model_utils.rs deleted file mode 100644 index 4116365..0000000 --- a/emgauwa-common/src/db/model_utils.rs +++ /dev/null @@ -1,137 +0,0 @@ -use chrono::{NaiveTime, Timelike}; -use serde::{Deserialize, Serialize}; -use sqlx::database::HasArguments; -use sqlx::encode::IsNull; -use sqlx::error::BoxDynError; -use sqlx::sqlite::{SqliteTypeInfo, SqliteValueRef}; -use sqlx::{Decode, Encode, Sqlite, Type}; - -use crate::db::DbPeriods; - -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -pub struct Period { - #[serde(with = "period_format")] - pub start: NaiveTime, - #[serde(with = "period_format")] - pub end: NaiveTime, -} - -mod period_format { - use chrono::NaiveTime; - use serde::{self, Deserialize, Deserializer, Serializer}; - - const FORMAT: &str = "%H:%M"; - - pub fn serialize(time: &NaiveTime, serializer: S) -> Result - where - S: Serializer, - { - let s = format!("{}", time.format(FORMAT)); - serializer.serialize_str(&s) - } - - pub fn deserialize<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - NaiveTime::parse_from_str(&s, FORMAT).map_err(serde::de::Error::custom) - } -} - -impl Period { - pub fn new(start: NaiveTime, end: NaiveTime) -> Self { - Period { start, end } - } - - pub fn new_on() -> Self { - Period { - start: NaiveTime::MIN, - end: NaiveTime::MIN, - } - } - - pub fn is_on(&self, now: &NaiveTime) -> bool { - self.start.eq(&self.end) || (self.start.le(now) && self.end.gt(now)) - } - - pub fn get_next_time(&self, now: &NaiveTime) -> Option { - if self.start.eq(&self.end) { - // this period is always on - return None; - } - - let start_after_now = self.start.gt(now); - let end_after_now = self.end.gt(now); - let start_before_end = self.start.lt(&self.end); - - match (start_after_now, end_after_now, start_before_end) { - (false, false, _) => None, // both before now - (true, false, _) => Some(self.start), // only start after now - (false, true, _) => Some(self.end), // only end after now - (true, true, true) => Some(self.start), // both after now but start first - (true, true, false) => Some(self.end), // both after now but end first - } - } -} - -impl Type for DbPeriods { - fn type_info() -> SqliteTypeInfo { - <&[u8] as Type>::type_info() - } - - fn compatible(ty: &SqliteTypeInfo) -> bool { - <&[u8] as Type>::compatible(ty) - } -} - -impl<'q> Encode<'q, Sqlite> for DbPeriods { - //noinspection DuplicatedCode - fn encode_by_ref(&self, buf: &mut >::ArgumentBuffer) -> IsNull { - <&Vec as Encode>::encode(&Vec::from(self), buf) - } -} - -impl<'r> Decode<'r, Sqlite> for DbPeriods { - fn decode(value: SqliteValueRef<'r>) -> Result { - let blob = <&[u8] as Decode>::decode(value)?; - Ok(DbPeriods::from(Vec::from(blob))) - } -} - -impl From<&DbPeriods> for Vec { - fn from(periods: &DbPeriods) -> Vec { - periods - .0 - .iter() - .flat_map(|period| { - let vec = vec![ - period.start.hour() as u8, - period.start.minute() as u8, - period.end.hour() as u8, - period.end.minute() as u8, - ]; - vec - }) - .collect() - } -} - -impl From> for DbPeriods { - fn from(value: Vec) -> Self { - let mut vec = Vec::new(); - for i in (3..value.len()).step_by(4) { - let start_val_h: u32 = value[i - 3] as u32; - let start_val_m: u32 = value[i - 2] as u32; - let end_val_h: u32 = value[i - 1] as u32; - let end_val_m: u32 = value[i] as u32; - vec.push(Period { - start: NaiveTime::from_hms_opt(start_val_h, start_val_m, 0) - .expect("Failed to parse period start time from database"), - end: NaiveTime::from_hms_opt(end_val_h, end_val_m, 0) - .expect("Failed to parse period end time from database"), - }); - } - DbPeriods(vec) - } -} diff --git a/emgauwa-common/src/db/relays.rs b/emgauwa-common/src/db/relays.rs deleted file mode 100644 index 2ac448a..0000000 --- a/emgauwa-common/src/db/relays.rs +++ /dev/null @@ -1,177 +0,0 @@ -use std::ops::DerefMut; - -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbController, DbJunctionRelaySchedule, DbJunctionTag, DbSchedule, DbTag}; -use crate::errors::DatabaseError; -use crate::types::Weekday; -use crate::utils; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DbRelay { - #[serde(skip)] - pub id: i64, - pub name: String, - pub number: i64, - #[serde(skip)] - pub controller_id: i64, -} - - -impl DbRelay { - pub async fn get_all(conn: &mut PoolConnection) -> Result, DatabaseError> { - sqlx::query_as!(DbRelay, "SELECT * FROM relays") - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get( - conn: &mut PoolConnection, - id: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbRelay, "SELECT * FROM relays WHERE id = ?", id) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_controller_and_num( - conn: &mut PoolConnection, - controller: &DbController, - number: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbRelay, - "SELECT * FROM relays WHERE controller_id = ? AND number = ?", - controller.id, - number - ) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_controller_and_num_or_create( - conn: &mut PoolConnection, - controller: &DbController, - number: i64, - new_name: &str, - ) -> Result<(DbRelay, bool), DatabaseError> { - match DbRelay::get_by_controller_and_num(conn, controller, number).await? { - Some(relay) => Ok((relay, false)), - None => { - let relay = DbRelay::create(conn, new_name, number, controller).await?; - Ok((relay, true)) - } - } - } - - pub async fn get_by_tag( - conn: &mut PoolConnection, - tag: &DbTag, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbRelay, "SELECT relay.* FROM relays AS relay INNER JOIN junction_tag ON junction_tag.relay_id = relay.id WHERE junction_tag.tag_id = ?", tag.id) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn create( - conn: &mut PoolConnection, - new_name: &str, - new_number: i64, - new_controller: &DbController, - ) -> Result { - sqlx::query_as!( - DbRelay, - "INSERT INTO relays (name, number, controller_id) VALUES (?, ?, ?) RETURNING *", - new_name, - new_number, - new_controller.id, - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } - - pub async fn delete(&self, conn: &mut PoolConnection) -> Result<(), DatabaseError> { - sqlx::query!("DELETE FROM relays WHERE id = ?", self.id) - .execute(conn.deref_mut()) - .await - .map(|res| match res.rows_affected() { - 0 => Err(DatabaseError::DeleteError), - _ => Ok(()), - })? - } - - pub async fn update( - &self, - conn: &mut PoolConnection, - new_name: &str, - ) -> Result { - sqlx::query!("UPDATE relays SET name = ? WHERE id = ?", new_name, self.id,) - .execute(conn.deref_mut()) - .await?; - - DbRelay::get(conn, self.id) - .await? - .ok_or(DatabaseError::UpdateGetError) - } - - pub async fn get_controller( - &self, - conn: &mut PoolConnection, - ) -> Result { - DbController::get(conn, self.controller_id) - .await? - .ok_or(DatabaseError::NotFound) - } - - pub async fn get_tags( - &self, - conn: &mut PoolConnection, - ) -> Result, DatabaseError> { - sqlx::query_scalar!("SELECT tag FROM tags INNER JOIN junction_tag ON junction_tag.tag_id = tags.id WHERE junction_tag.relay_id = ?", self.id) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn set_tags( - &self, - conn: &mut PoolConnection, - new_tags: &[String], - ) -> Result<(), DatabaseError> { - sqlx::query!("DELETE FROM junction_tag WHERE relay_id = ?", self.id) - .execute(conn.deref_mut()) - .await?; - - for new_tag in new_tags { - let tag: DbTag = DbTag::get_by_tag_or_create(conn, new_tag).await?; - DbJunctionTag::link_relay(conn, &tag, self).await?; - } - Ok(()) - } - - pub async fn reload( - &self, - conn: &mut PoolConnection, - ) -> Result { - Self::get(conn, self.id) - .await? - .ok_or(DatabaseError::NotFound) - } - - pub async fn get_active_schedule( - &self, - conn: &mut PoolConnection, - ) -> Result { - let weekday = utils::get_weekday(); - DbJunctionRelaySchedule::get_schedule(conn, self, weekday as Weekday) - .await? - .ok_or(DatabaseError::NotFound) - } -} diff --git a/emgauwa-common/src/db/schedules.rs b/emgauwa-common/src/db/schedules.rs deleted file mode 100644 index 6a792fd..0000000 --- a/emgauwa-common/src/db/schedules.rs +++ /dev/null @@ -1,209 +0,0 @@ -use std::borrow::Borrow; -use std::ops::DerefMut; - -use chrono::NaiveTime; -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::model_utils::Period; -use crate::db::{DbJunctionTag, DbTag}; -use crate::errors::DatabaseError; -use crate::types::ScheduleUid; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DbSchedule { - #[serde(skip)] - pub id: i64, - #[serde(rename = "id")] - pub uid: ScheduleUid, - pub name: String, - pub periods: DbPeriods, -} - -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] -pub struct DbPeriods(pub Vec); - -impl DbSchedule { - pub async fn get_all( - conn: &mut PoolConnection, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbSchedule, "SELECT * FROM schedules") - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get( - conn: &mut PoolConnection, - id: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbSchedule, "SELECT * FROM schedules WHERE id = ?", id) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_uid( - conn: &mut PoolConnection, - filter_uid: &ScheduleUid, - ) -> Result, DatabaseError> { - sqlx::query_as!( - DbSchedule, - "SELECT * FROM schedules WHERE uid = ?", - filter_uid - ) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_tag( - conn: &mut PoolConnection, - tag: &DbTag, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbSchedule, "SELECT schedule.* FROM schedules AS schedule INNER JOIN junction_tag ON junction_tag.schedule_id = schedule.id WHERE junction_tag.tag_id = ?", tag.id) - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn delete_by_uid( - conn: &mut PoolConnection, - filter_uid: ScheduleUid, - ) -> Result<(), DatabaseError> { - let filter_uid = match filter_uid { - ScheduleUid::Off => Err(DatabaseError::Protected), - ScheduleUid::On => Err(DatabaseError::Protected), - ScheduleUid::Any(_) => Ok(filter_uid), - }?; - - if sqlx::query_scalar!("SELECT 1 FROM schedules WHERE uid = ?", filter_uid) - .fetch_optional(conn.deref_mut()) - .await? - .is_none() - { - return Err(DatabaseError::NotFound); - } - - sqlx::query!("DELETE FROM schedules WHERE uid = ?", filter_uid) - .execute(conn.deref_mut()) - .await - .map(|res| match res.rows_affected() { - 0 => Err(DatabaseError::DeleteError), - _ => Ok(()), - })? - } - - pub async fn create( - conn: &mut PoolConnection, - new_uid: ScheduleUid, - new_name: &str, - new_periods: &DbPeriods, - ) -> Result { - sqlx::query_as!( - DbSchedule, - "INSERT INTO schedules (uid, name, periods) VALUES (?, ?, ?) RETURNING *", - new_uid, - new_name, - new_periods, - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } - - pub async fn get_by_uid_or_create( - conn: &mut PoolConnection, - uid: ScheduleUid, - name: &str, - periods: &DbPeriods, - ) -> Result<(DbSchedule, bool), DatabaseError> { - match DbSchedule::get_by_uid(conn, &uid).await? { - Some(schedule) => Ok((schedule, false)), - None => { - let schedule = DbSchedule::create(conn, uid, name, periods).await?; - Ok((schedule, true)) - } - } - } - - pub async fn get_on(conn: &mut PoolConnection) -> Result { - if let Some(schedule) = DbSchedule::get_by_uid(conn, &ScheduleUid::On).await? { - return Ok(schedule); - } - let periods = DbPeriods(vec![Period::new_on()]); - Self::create(conn, ScheduleUid::On, "On", &periods).await - } - - pub async fn get_off(conn: &mut PoolConnection) -> Result { - if let Some(schedule) = DbSchedule::get_by_uid(conn, &ScheduleUid::Off).await? { - return Ok(schedule); - } - let periods = DbPeriods(vec![]); - Self::create(conn, ScheduleUid::Off, "Off", &periods).await - } - - pub async fn update( - &self, - conn: &mut PoolConnection, - new_name: &str, - new_periods: &DbPeriods, - ) -> Result { - // overwrite periods on protected schedules - let new_periods = match self.uid { - ScheduleUid::Off | ScheduleUid::On => self.periods.borrow(), - ScheduleUid::Any(_) => new_periods, - }; - - sqlx::query!( - "UPDATE schedules SET name = ?, periods = ? WHERE id = ?", - new_name, - new_periods, - self.id, - ) - .execute(conn.deref_mut()) - .await?; - - DbSchedule::get(conn, self.id) - .await? - .ok_or(DatabaseError::UpdateGetError) - } - - pub async fn get_tags( - &self, - conn: &mut PoolConnection, - ) -> Result, DatabaseError> { - Ok(sqlx::query_scalar!("SELECT tag FROM tags INNER JOIN junction_tag ON junction_tag.tag_id = tags.id WHERE junction_tag.schedule_id = ?", self.id) - .fetch_all(conn.deref_mut()) - .await?) - } - - pub async fn set_tags( - &self, - conn: &mut PoolConnection, - new_tags: &[String], - ) -> Result<(), DatabaseError> { - sqlx::query!("DELETE FROM junction_tag WHERE schedule_id = ?", self.id) - .execute(conn.deref_mut()) - .await?; - - for new_tag in new_tags { - let tag: DbTag = DbTag::get_by_tag_or_create(conn, new_tag).await?; - DbJunctionTag::link_schedule(conn, &tag, self).await?; - } - Ok(()) - } - - pub fn is_on(&self, now: &NaiveTime) -> bool { - self.periods.0.iter().any(|period| period.is_on(now)) - } - - pub fn get_next_time(&self, now: &NaiveTime) -> Option { - self.periods - .0 - .iter() - .filter_map(|period| period.get_next_time(now)) - .min() - } -} diff --git a/emgauwa-common/src/db/tag.rs b/emgauwa-common/src/db/tag.rs deleted file mode 100644 index 9c15f79..0000000 --- a/emgauwa-common/src/db/tag.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::ops::DerefMut; - -use serde_derive::Serialize; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::errors::DatabaseError; - -#[derive(Debug, Serialize, Clone)] -pub struct DbTag { - pub id: i64, - pub tag: String, -} - -impl DbTag { - pub async fn create( - conn: &mut PoolConnection, - new_tag: &str, - ) -> Result { - if new_tag.is_empty() { - return Err(DatabaseError::EmptyDataInsert); - } - - sqlx::query_as!( - DbTag, - "INSERT INTO tags (tag) VALUES (?) RETURNING *", - new_tag - ) - .fetch_optional(conn.deref_mut()) - .await? - .ok_or(DatabaseError::InsertGetError) - } - - pub async fn get_all(conn: &mut PoolConnection) -> Result, DatabaseError> { - sqlx::query_as!(DbTag, "SELECT * FROM tags") - .fetch_all(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get( - conn: &mut PoolConnection, - id: i64, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbTag, "SELECT * FROM tags WHERE id = ?", id) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn get_by_tag_or_create( - conn: &mut PoolConnection, - target_tag: &str, - ) -> Result { - match DbTag::get_by_tag(conn, target_tag).await? { - Some(tag) => Ok(tag), - None => DbTag::create(conn, target_tag).await, - } - } - - pub async fn get_by_tag( - conn: &mut PoolConnection, - target_tag: &str, - ) -> Result, DatabaseError> { - sqlx::query_as!(DbTag, "SELECT * FROM tags WHERE tag = ?", target_tag) - .fetch_optional(conn.deref_mut()) - .await - .map_err(DatabaseError::from) - } - - pub async fn delete_by_tag( - conn: &mut PoolConnection, - filter_tag: &str, - ) -> Result<(), DatabaseError> { - if sqlx::query_scalar!("SELECT 1 FROM tags WHERE tag = ?", filter_tag) - .fetch_optional(conn.deref_mut()) - .await? - .is_none() - { - return Err(DatabaseError::NotFound); - } - - sqlx::query!("DELETE FROM tags WHERE tag = ?", filter_tag) - .execute(conn.deref_mut()) - .await - .map(|res| match res.rows_affected() { - 0 => Err(DatabaseError::DeleteError), - _ => Ok(()), - })? - } -} diff --git a/emgauwa-common/src/drivers/gpio.rs b/emgauwa-common/src/drivers/gpio.rs deleted file mode 100644 index 7847d43..0000000 --- a/emgauwa-common/src/drivers/gpio.rs +++ /dev/null @@ -1,35 +0,0 @@ -use rppal::gpio::{Gpio, OutputPin}; - -use crate::drivers::RelayDriver; -use crate::errors::EmgauwaError; - -pub struct GpioDriver { - pub gpio: OutputPin, - pub inverted: bool, -} - -impl GpioDriver { - pub fn new(pin: u8, inverted: bool) -> Result { - let gpio = Gpio::new()?.get(pin)?.into_output(); - Ok(Self { gpio, inverted }) - } -} - -impl RelayDriver for GpioDriver { - fn set(&mut self, value: bool) -> Result<(), EmgauwaError> { - if self.get_high(value) { - self.gpio.set_high(); - } else { - self.gpio.set_low(); - } - Ok(()) - } - - fn get_pin(&self) -> u8 { - self.gpio.pin() - } - - fn get_inverted(&self) -> bool { - self.inverted - } -} diff --git a/emgauwa-common/src/drivers/mod.rs b/emgauwa-common/src/drivers/mod.rs deleted file mode 100644 index abae75a..0000000 --- a/emgauwa-common/src/drivers/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -mod gpio; -mod null; -mod piface; - -pub use gpio::GpioDriver; -pub use null::NullDriver; -pub use piface::PiFaceDriver; - -use crate::errors::EmgauwaError; - -pub trait RelayDriver { - fn get_high(&self, value: bool) -> bool { - value ^ self.get_inverted() - } - - fn set(&mut self, value: bool) -> Result<(), EmgauwaError>; - fn get_pin(&self) -> u8; - fn get_inverted(&self) -> bool; -} diff --git a/emgauwa-common/src/drivers/null.rs b/emgauwa-common/src/drivers/null.rs deleted file mode 100644 index be4e8b9..0000000 --- a/emgauwa-common/src/drivers/null.rs +++ /dev/null @@ -1,26 +0,0 @@ -use crate::drivers::RelayDriver; -use crate::errors::EmgauwaError; - -pub struct NullDriver { - pub pin: u8, -} - -impl NullDriver { - pub fn new(pin: u8) -> Self { - Self { pin } - } -} - -impl RelayDriver for NullDriver { - fn set(&mut self, _value: bool) -> Result<(), EmgauwaError> { - Ok(()) - } - - fn get_pin(&self) -> u8 { - self.pin - } - - fn get_inverted(&self) -> bool { - false - } -} diff --git a/emgauwa-common/src/drivers/piface.rs b/emgauwa-common/src/drivers/piface.rs deleted file mode 100644 index 7bc20da..0000000 --- a/emgauwa-common/src/drivers/piface.rs +++ /dev/null @@ -1,52 +0,0 @@ -use rppal_pfd::{ - ChipSelect, HardwareAddress, OutputPin, PiFaceDigital, PiFaceDigitalError, SpiBus, SpiMode, -}; - -use crate::drivers::RelayDriver; -use crate::errors::EmgauwaError; - -pub struct PiFaceDriver { - pub pfd_pin: OutputPin, -} - -impl PiFaceDriver { - pub fn new(pin: u8, pfd: &Option) -> Result { - let pfd = pfd.as_ref().ok_or(EmgauwaError::Hardware(String::from( - "PiFaceDigital not initialized", - )))?; - let pfd_pin = pfd.get_output_pin(pin)?; - Ok(Self { pfd_pin }) - } - - pub fn init_piface() -> Result { - let mut pfd = PiFaceDigital::new( - HardwareAddress::new(0)?, - SpiBus::Spi0, - ChipSelect::Cs0, - 100_000, - SpiMode::Mode0, - )?; - pfd.init()?; - - Ok(pfd) - } -} - -impl RelayDriver for PiFaceDriver { - fn set(&mut self, value: bool) -> Result<(), EmgauwaError> { - if self.get_high(value) { - self.pfd_pin.set_high().map_err(PiFaceDigitalError::from)?; - } else { - self.pfd_pin.set_low().map_err(PiFaceDigitalError::from)?; - } - Ok(()) - } - - fn get_pin(&self) -> u8 { - self.pfd_pin.get_pin_number() - } - - fn get_inverted(&self) -> bool { - false - } -} diff --git a/emgauwa-common/src/errors/api_error.rs b/emgauwa-common/src/errors/api_error.rs deleted file mode 100644 index bba2248..0000000 --- a/emgauwa-common/src/errors/api_error.rs +++ /dev/null @@ -1,22 +0,0 @@ -use actix_web::http::StatusCode; - -#[derive(Debug)] -pub enum ApiError { - ProtectedSchedule, -} - -impl ApiError { - pub fn get_code(&self) -> StatusCode { - match self { - ApiError::ProtectedSchedule => StatusCode::FORBIDDEN, - } - } -} - -impl From<&ApiError> for String { - fn from(err: &ApiError) -> Self { - match err { - ApiError::ProtectedSchedule => String::from("the targeted schedule is protected"), - } - } -} diff --git a/emgauwa-common/src/errors/database_error.rs b/emgauwa-common/src/errors/database_error.rs deleted file mode 100644 index cd9f838..0000000 --- a/emgauwa-common/src/errors/database_error.rs +++ /dev/null @@ -1,85 +0,0 @@ -use actix_web::http::StatusCode; -use actix_web::HttpResponse; -use serde::ser::SerializeStruct; -use serde::{Serialize, Serializer}; -use sqlx::migrate::MigrateError; -use sqlx::Error; - -#[derive(Debug)] -pub enum DatabaseError { - DeleteError, - InsertError, - InsertGetError, - NotFound, - Protected, - EmptyDataInsert, - UpdateError, - UpdateGetError, - MigrationError(MigrateError), - Unknown(Error), -} - -impl DatabaseError { - pub fn get_code(&self) -> StatusCode { - match self { - DatabaseError::NotFound => StatusCode::NOT_FOUND, - DatabaseError::Protected => StatusCode::FORBIDDEN, - _ => StatusCode::INTERNAL_SERVER_ERROR, - } - } -} - -impl Serialize for DatabaseError { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut s = serializer.serialize_struct("error", 3)?; - s.serialize_field("type", "database-error")?; - s.serialize_field("code", &self.get_code().as_u16())?; - s.serialize_field("description", &String::from(self))?; - s.end() - } -} - -impl From<&DatabaseError> for String { - fn from(err: &DatabaseError) -> Self { - String::from(match err { - DatabaseError::InsertError => "error on inserting into database", - DatabaseError::InsertGetError => { - "error on retrieving new entry from database (your entry was saved)" - } - DatabaseError::NotFound => "model was not found in database", - DatabaseError::DeleteError => "error on deleting from database", - DatabaseError::Protected => "model is protected", - DatabaseError::UpdateError => "error on updating the model", - DatabaseError::UpdateGetError => { - "error on retrieving updated model from database (your entry was saved)" - } - DatabaseError::MigrationError(_) => "error on running migrations", - DatabaseError::Unknown(_) => "unknown error", - DatabaseError::EmptyDataInsert => "tried to insert empty data", - }) - } -} - -impl From for HttpResponse { - fn from(err: DatabaseError) -> Self { - HttpResponse::build(err.get_code()).json(err) - } -} - -impl From for DatabaseError { - fn from(value: Error) -> Self { - match value { - Error::RowNotFound => DatabaseError::NotFound, - _ => DatabaseError::Unknown(value), - } - } -} - -impl From for DatabaseError { - fn from(value: MigrateError) -> Self { - Self::MigrationError(value) - } -} diff --git a/emgauwa-common/src/errors/emgauwa_error.rs b/emgauwa-common/src/errors/emgauwa_error.rs deleted file mode 100644 index 0e8ce65..0000000 --- a/emgauwa-common/src/errors/emgauwa_error.rs +++ /dev/null @@ -1,161 +0,0 @@ -use std::error::Error; -use std::fmt::{Debug, Display, Formatter}; -use std::io::ErrorKind; - -use actix::MailboxError; -use actix_web::http::StatusCode; -use actix_web::HttpResponse; -use config::ConfigError; -use rppal::gpio; -use rppal_mcp23s17::Mcp23s17Error; -use rppal_pfd::PiFaceDigitalError; -use serde::ser::SerializeStruct; -use serde::{Serialize, Serializer}; - -use crate::errors::{ApiError, DatabaseError}; -use crate::types::EmgauwaUid; - -#[derive(Debug)] -pub enum EmgauwaError { - Api(ApiError), - Uid(uuid::Error), - Serialization(serde_json::Error), - Database(DatabaseError), - Other(String), - Internal(String), - Connection(EmgauwaUid), - Hardware(String), -} - -impl EmgauwaError { - fn get_code(&self) -> StatusCode { - match self { - EmgauwaError::Api(err) => err.get_code(), - EmgauwaError::Serialization(_) => StatusCode::INTERNAL_SERVER_ERROR, - EmgauwaError::Database(err) => err.get_code(), - EmgauwaError::Uid(_) => StatusCode::BAD_REQUEST, - EmgauwaError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR, - EmgauwaError::Connection(_) => StatusCode::GATEWAY_TIMEOUT, - EmgauwaError::Other(_) => StatusCode::INTERNAL_SERVER_ERROR, - EmgauwaError::Hardware(_) => StatusCode::INTERNAL_SERVER_ERROR, - } - } -} - -impl From<&EmgauwaError> for String { - fn from(err: &EmgauwaError) -> Self { - match err { - EmgauwaError::Api(err) => String::from(err), - EmgauwaError::Serialization(_) => String::from("error during (de-)serialization"), - EmgauwaError::Database(err) => String::from(err), - EmgauwaError::Uid(_) => String::from("the uid is in a bad format"), - EmgauwaError::Internal(_) => String::from("internal error"), - EmgauwaError::Connection(_) => String::from("the target controller is not connected"), - EmgauwaError::Other(err) => format!("other error: {}", err), - EmgauwaError::Hardware(err) => format!("hardware error: {}", err), - } - } -} - -impl From for EmgauwaError { - fn from(value: ApiError) -> Self { - EmgauwaError::Api(value) - } -} - -impl From for EmgauwaError { - fn from(value: DatabaseError) -> Self { - EmgauwaError::Database(value) - } -} - -impl From for EmgauwaError { - fn from(value: serde_json::Error) -> Self { - EmgauwaError::Serialization(value) - } -} - -impl From for EmgauwaError { - fn from(value: sqlx::Error) -> Self { - EmgauwaError::Database(DatabaseError::from(value)) - } -} - -impl From for EmgauwaError { - fn from(value: uuid::Error) -> Self { - EmgauwaError::Uid(value) - } -} - -impl From for EmgauwaError { - fn from(value: MailboxError) -> Self { - EmgauwaError::Internal(value.to_string()) - } -} - -impl From for EmgauwaError { - fn from(value: ConfigError) -> Self { - Self::Other(value.to_string()) - } -} - -impl From for EmgauwaError { - fn from(value: gpio::Error) -> Self { - Self::Hardware(value.to_string()) - } -} - -impl From for EmgauwaError { - fn from(value: PiFaceDigitalError) -> Self { - match value { - PiFaceDigitalError::Mcp23s17Error { source } => match source { - Mcp23s17Error::SpiError { source } => Self::Hardware(source.to_string()), - _ => Self::Hardware(source.to_string()), - }, - PiFaceDigitalError::GpioError { source } => Self::Hardware(source.to_string()), - _ => Self::Hardware(value.to_string()), - } - } -} - -impl From<&EmgauwaError> for HttpResponse { - fn from(err: &EmgauwaError) -> Self { - HttpResponse::build(err.get_code()).json(err) - } -} - -impl Error for EmgauwaError {} - -impl From for std::io::Error { - fn from(value: EmgauwaError) -> Self { - std::io::Error::new(ErrorKind::Other, value) - } -} - -impl Serialize for EmgauwaError { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut s = serializer.serialize_struct("error", 2)?; - s.serialize_field("code", &self.get_code().as_u16())?; - s.serialize_field("description", &String::from(self))?; - s.end() - } -} - -impl Display for EmgauwaError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}: {}", self.get_code(), String::from(self)) - } -} - -impl actix_web::error::ResponseError for EmgauwaError { - fn status_code(&self) -> StatusCode { - self.get_code() - } - - fn error_response(&self) -> HttpResponse { - HttpResponse::from(self) - } -} diff --git a/emgauwa-common/src/errors/mod.rs b/emgauwa-common/src/errors/mod.rs deleted file mode 100644 index 0209bcc..0000000 --- a/emgauwa-common/src/errors/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod api_error; -mod database_error; -mod emgauwa_error; - -pub use api_error::ApiError; -pub use database_error::DatabaseError; -pub use emgauwa_error::EmgauwaError; diff --git a/emgauwa-common/src/lib.rs b/emgauwa-common/src/lib.rs deleted file mode 100644 index 14609b9..0000000 --- a/emgauwa-common/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod constants; -pub mod db; -pub mod drivers; -pub mod errors; -pub mod models; -pub mod settings; -pub mod types; -pub mod utils; diff --git a/emgauwa-common/src/models/controller.rs b/emgauwa-common/src/models/controller.rs deleted file mode 100644 index 96d7b00..0000000 --- a/emgauwa-common/src/models/controller.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::time::Instant; - -use actix::MessageResponse; -use chrono::NaiveTime; -use futures::executor::block_on; -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::DbController; -use crate::errors::{DatabaseError, EmgauwaError}; -use crate::models::{convert_db_list_cache, FromDbModel, Relay}; -use crate::types::RelayStates; - -#[derive(Serialize, Deserialize, Debug, Clone, MessageResponse)] -pub struct Controller { - #[serde(flatten)] - pub c: DbController, - pub relays: Vec, -} - -impl FromDbModel for Controller { - type DbModel = DbController; - type DbModelCache = Vec; - - fn from_db_model( - conn: &mut PoolConnection, - db_model: Self::DbModel, - ) -> Result { - let relays_db = block_on(db_model.get_relays(conn))?; - let cache = convert_db_list_cache(conn, relays_db, db_model.clone())?; - Self::from_db_model_cache(conn, db_model, cache) - } - - fn from_db_model_cache( - _conn: &mut PoolConnection, - db_model: Self::DbModel, - cache: Self::DbModelCache, - ) -> Result { - Ok(Controller { - c: db_model, - relays: cache, - }) - } -} - -impl Controller { - pub fn reload(&mut self, conn: &mut PoolConnection) -> Result<(), EmgauwaError> { - self.c = block_on(self.c.reload(conn))?; - for relay in &mut self.relays { - relay.reload(conn)?; - } - Ok(()) - } - - pub fn apply_relay_states(&mut self, relay_states: &RelayStates) { - self.relays - .iter_mut() - .zip(relay_states.iter()) - .for_each(|(relay, is_on)| { - relay.is_on = *is_on; - }); - } - - pub fn get_relay_states(&self) -> RelayStates { - self.relays.iter().map(|r| r.is_on).collect() - } - - pub fn get_next_time(&self, now: &NaiveTime) -> Option { - self.relays - .iter() - .filter_map(|r| r.active_schedule.get_next_time(now)) - .min() - } - - pub fn relay_pulse(&mut self, relay_num: i64, until: Instant) -> Result<(), EmgauwaError> { - let relay = self - .relays - .iter_mut() - .find(|r| r.r.number == relay_num) - .ok_or(EmgauwaError::Other(String::from("Relay not found")))?; - - relay.pulsing = Some(until); - Ok(()) - } -} diff --git a/emgauwa-common/src/models/macro.rs b/emgauwa-common/src/models/macro.rs deleted file mode 100644 index fbe9dbb..0000000 --- a/emgauwa-common/src/models/macro.rs +++ /dev/null @@ -1,42 +0,0 @@ -use futures::executor::block_on; -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::DbMacro; -use crate::errors::DatabaseError; -use crate::models::{convert_db_list, FromDbModel, MacroAction}; - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Macro { - #[serde(flatten)] - pub m: DbMacro, - pub actions: Vec, -} - - -impl FromDbModel for Macro { - type DbModel = DbMacro; - type DbModelCache = (); - - fn from_db_model( - conn: &mut PoolConnection, - db_model: Self::DbModel, - ) -> Result { - Self::from_db_model_cache(conn, db_model, ()) - } - - fn from_db_model_cache( - conn: &mut PoolConnection, - db_model: Self::DbModel, - _cache: Self::DbModelCache, - ) -> Result { - let actions_db = block_on(db_model.get_actions(conn))?; - let actions: Vec = convert_db_list(conn, actions_db)?; - - Ok(Macro { - m: db_model, - actions, - }) - } -} diff --git a/emgauwa-common/src/models/macro_action.rs b/emgauwa-common/src/models/macro_action.rs deleted file mode 100644 index d7b5aca..0000000 --- a/emgauwa-common/src/models/macro_action.rs +++ /dev/null @@ -1,56 +0,0 @@ -use futures::executor::block_on; -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbJunctionRelaySchedule, DbMacroAction}; -use crate::errors::{DatabaseError, EmgauwaError}; -use crate::models::{FromDbModel, Relay, Schedule}; - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct MacroAction { - pub schedule: Schedule, - pub relay: Relay, - pub weekday: i64, -} - - -impl FromDbModel for MacroAction { - type DbModel = DbMacroAction; - type DbModelCache = (); - - fn from_db_model( - conn: &mut PoolConnection, - db_model: Self::DbModel, - ) -> Result { - Self::from_db_model_cache(conn, db_model, ()) - } - - fn from_db_model_cache( - conn: &mut PoolConnection, - db_model: Self::DbModel, - _cache: Self::DbModelCache, - ) -> Result { - let schedule_db = block_on(db_model.get_schedule(conn))?; - let schedule = Schedule::from_db_model(conn, schedule_db)?; - - let relay_db = block_on(db_model.get_relay(conn))?; - let relay = Relay::from_db_model(conn, relay_db)?; - - let weekday = db_model.weekday; - - Ok(MacroAction { - schedule, - relay, - weekday, - }) - } -} - -impl MacroAction { - pub async fn execute(&self, conn: &mut PoolConnection) -> Result<(), EmgauwaError> { - DbJunctionRelaySchedule::set_schedule(conn, &self.relay.r, &self.schedule.s, self.weekday) - .await?; - Ok(()) - } -} diff --git a/emgauwa-common/src/models/mod.rs b/emgauwa-common/src/models/mod.rs deleted file mode 100644 index 570bf48..0000000 --- a/emgauwa-common/src/models/mod.rs +++ /dev/null @@ -1,68 +0,0 @@ -mod controller; -mod r#macro; -mod macro_action; -mod relay; -mod schedule; -mod tag; - -pub use controller::Controller; -pub use macro_action::MacroAction; -pub use r#macro::Macro; -pub use relay::Relay; -pub use schedule::Schedule; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; -pub use tag::Tag; - -use crate::errors::DatabaseError; - -pub trait FromDbModel { - type DbModel: Clone; - type DbModelCache: Clone; - - fn from_db_model( - conn: &mut PoolConnection, - db_model: Self::DbModel, - ) -> Result - where - Self: Sized; - - fn from_db_model_cache( - conn: &mut PoolConnection, - db_model: Self::DbModel, - cache: Self::DbModelCache, - ) -> Result - where - Self: Sized; -} - -fn convert_db_list_generic( - conn: &mut PoolConnection, - db_models: Vec, - cache: Option, -) -> Result, DatabaseError> { - let mut result: Vec = Vec::new(); - for db_model in db_models { - let new = match &cache { - Some(c) => T::from_db_model_cache(conn, db_model, c.clone()), - None => T::from_db_model(conn, db_model), - }?; - result.push(new); - } - Ok(result) -} - -pub fn convert_db_list( - conn: &mut PoolConnection, - db_models: Vec, -) -> Result, DatabaseError> { - convert_db_list_generic(conn, db_models, None) -} - -pub fn convert_db_list_cache( - conn: &mut PoolConnection, - db_models: Vec, - cache: T::DbModelCache, -) -> Result, DatabaseError> { - convert_db_list_generic(conn, db_models, Some(cache)) -} diff --git a/emgauwa-common/src/models/relay.rs b/emgauwa-common/src/models/relay.rs deleted file mode 100644 index a7d0e60..0000000 --- a/emgauwa-common/src/models/relay.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::time::Instant; - -use chrono::NaiveTime; -use futures::executor::block_on; -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule}; -use crate::errors::DatabaseError; -use crate::models::FromDbModel; -use crate::types::EmgauwaUid; - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Relay { - #[serde(flatten)] - pub r: DbRelay, - pub controller: DbController, - pub controller_id: EmgauwaUid, - pub schedules: Vec, - pub active_schedule: DbSchedule, - pub is_on: Option, - pub tags: Vec, - - // for internal use only. - #[serde(skip)] - pub pulsing: Option, -} - - -impl FromDbModel for Relay { - type DbModel = DbRelay; - type DbModelCache = DbController; - - fn from_db_model( - conn: &mut PoolConnection, - db_model: Self::DbModel, - ) -> Result { - let cache = block_on(db_model.get_controller(conn))?; - Self::from_db_model_cache(conn, db_model, cache) - } - - fn from_db_model_cache( - conn: &mut PoolConnection, - db_model: Self::DbModel, - cache: Self::DbModelCache, - ) -> Result { - let tags = block_on(db_model.get_tags(conn))?; - let controller_id = cache.uid.clone(); - - let schedules = block_on(DbJunctionRelaySchedule::get_schedules(conn, &db_model))?; - let active_schedule = block_on(db_model.get_active_schedule(conn))?; - - let is_on = None; - - Ok(Relay { - r: db_model, - controller: cache, - controller_id, - schedules, - active_schedule, - is_on, - tags, - pulsing: None, - }) - } -} - -impl Relay { - pub fn reload(&mut self, conn: &mut PoolConnection) -> Result<(), DatabaseError> { - self.r = block_on(self.r.reload(conn))?; - self.schedules = block_on(DbJunctionRelaySchedule::get_schedules(conn, &self.r))?; - self.reload_active_schedule(conn)?; - - Ok(()) - } - - pub fn reload_active_schedule( - &mut self, - conn: &mut PoolConnection, - ) -> Result<(), DatabaseError> { - self.active_schedule = block_on(self.r.get_active_schedule(conn))?; - Ok(()) - } - - pub fn is_on(&self, now: &NaiveTime) -> bool { - self.active_schedule.is_on(now) - } - - pub fn get_next_time(&self, now: &NaiveTime) -> Option { - self.active_schedule.get_next_time(now) - } - - pub fn check_pulsing(&mut self, now: &Instant) -> Option { - match self.pulsing { - Some(dur_instant) => { - if dur_instant.lt(now) { - self.pulsing = None; - None - } else { - Some(dur_instant) - } - } - None => None, - } - } -} diff --git a/emgauwa-common/src/models/schedule.rs b/emgauwa-common/src/models/schedule.rs deleted file mode 100644 index 9bf07b4..0000000 --- a/emgauwa-common/src/models/schedule.rs +++ /dev/null @@ -1,41 +0,0 @@ -use futures::executor::block_on; -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::DbSchedule; -use crate::errors::DatabaseError; -use crate::models::FromDbModel; - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Schedule { - #[serde(flatten)] - pub s: DbSchedule, - pub tags: Vec, -} - -impl FromDbModel for Schedule { - type DbModel = DbSchedule; - type DbModelCache = Vec; - - fn from_db_model( - conn: &mut PoolConnection, - db_model: Self::DbModel, - ) -> Result { - let cache = block_on(db_model.get_tags(conn))?; - Self::from_db_model_cache(conn, db_model, cache) - } - - fn from_db_model_cache( - _conn: &mut PoolConnection, - db_model: Self::DbModel, - cache: Self::DbModelCache, - ) -> Result { - let schedule = db_model.clone(); - - Ok(Schedule { - s: schedule, - tags: cache, - }) - } -} diff --git a/emgauwa-common/src/models/tag.rs b/emgauwa-common/src/models/tag.rs deleted file mode 100644 index 7e23fb4..0000000 --- a/emgauwa-common/src/models/tag.rs +++ /dev/null @@ -1,49 +0,0 @@ -use actix::MessageResponse; -use futures::executor::block_on; -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbRelay, DbSchedule, DbTag}; -use crate::errors::DatabaseError; -use crate::models::{convert_db_list, FromDbModel, Relay, Schedule}; - -#[derive(Serialize, Deserialize, Debug, Clone, MessageResponse)] -pub struct Tag { - pub tag: String, - pub relays: Vec, - pub schedules: Vec, -} - -impl FromDbModel for Tag { - type DbModel = DbTag; - type DbModelCache = (Vec, Vec); - - fn from_db_model( - conn: &mut PoolConnection, - db_model: Self::DbModel, - ) -> Result { - let db_schedules = block_on(DbSchedule::get_by_tag(conn, &db_model))?; - let schedules: Vec = convert_db_list(conn, db_schedules)?; - - let db_relays = block_on(DbRelay::get_by_tag(conn, &db_model))?; - let relays: Vec = convert_db_list(conn, db_relays)?; - - let cache = (relays, schedules); - Self::from_db_model_cache(conn, db_model, cache) - } - - fn from_db_model_cache( - _conn: &mut PoolConnection, - db_model: Self::DbModel, - cache: Self::DbModelCache, - ) -> Result { - let tag = db_model.tag.clone(); - let (relays, schedules) = cache; - Ok(Tag { - tag, - relays, - schedules, - }) - } -} diff --git a/emgauwa-common/src/settings.rs b/emgauwa-common/src/settings.rs deleted file mode 100644 index bc966dd..0000000 --- a/emgauwa-common/src/settings.rs +++ /dev/null @@ -1,67 +0,0 @@ -use serde_derive::Deserialize; - -use crate::constants; -use crate::errors::EmgauwaError; - -#[derive(Clone, Debug, Deserialize)] -#[serde(default)] -#[allow(unused)] -pub struct Server { - pub host: String, - pub port: u16, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(default)] -#[allow(unused)] -pub struct Logging { - pub level: String, - pub file: String, -} - -#[derive(Clone, Debug, Deserialize, Default)] -#[serde(default)] -#[allow(unused)] -pub struct Permissions { - pub user: String, - pub group: String, -} - -impl Default for Server { - fn default() -> Self { - Server { - host: String::from("127.0.0.1"), - port: constants::DEFAULT_PORT, - } - } -} - -impl Default for Logging { - fn default() -> Self { - Logging { - level: String::from("info"), - file: String::from("stdout"), - } - } -} - -pub fn load(config_name: &str, env_prefix: &str) -> Result -where - for<'de> T: serde::Deserialize<'de>, -{ - let etc_file = - config::File::with_name(&format!("/etc/emgauwa/{}", config_name)).required(false); - let local_file = config::File::with_name(&format!("./emgauwa-{}", config_name)).required(false); - - config::Config::builder() - .add_source(etc_file) - .add_source(local_file) - .add_source( - config::Environment::with_prefix(&format!("EMGAUWA_{}", env_prefix)) - .prefix_separator("__") - .separator("__"), - ) - .build()? - .try_deserialize::() - .map_err(EmgauwaError::from) -} diff --git a/emgauwa-common/src/types/emgauwa_uid.rs b/emgauwa-common/src/types/emgauwa_uid.rs deleted file mode 100644 index 8d29fbd..0000000 --- a/emgauwa-common/src/types/emgauwa_uid.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::fmt::{Display, Formatter}; -use std::str::FromStr; - -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use sqlx::database::HasArguments; -use sqlx::encode::IsNull; -use sqlx::error::BoxDynError; -use sqlx::sqlite::{SqliteTypeInfo, SqliteValueRef}; -use sqlx::{Decode, Encode, Sqlite, Type}; -use uuid::Uuid; - -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub struct EmgauwaUid(Uuid); - -impl Default for EmgauwaUid { - fn default() -> Self { - Self(Uuid::new_v4()) - } -} - -impl Display for EmgauwaUid { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", String::from(self)) - } -} - -impl Serialize for EmgauwaUid { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - String::from(self).serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for EmgauwaUid { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Self::try_from(String::deserialize(deserializer)?.as_str()) - .map_err(|_| serde::de::Error::custom("invalid uid")) - } -} - -impl From<&EmgauwaUid> for String { - fn from(uid: &EmgauwaUid) -> String { - uid.0.as_hyphenated().to_string() - } -} - -impl Type for EmgauwaUid { - fn type_info() -> SqliteTypeInfo { - <&[u8] as Type>::type_info() - } - - fn compatible(ty: &SqliteTypeInfo) -> bool { - <&[u8] as Type>::compatible(ty) - } -} - -impl<'q> Encode<'q, Sqlite> for EmgauwaUid { - //noinspection DuplicatedCode - fn encode_by_ref(&self, buf: &mut >::ArgumentBuffer) -> IsNull { - as Encode>::encode(Vec::from(self), buf) - } -} - -impl<'r> Decode<'r, Sqlite> for EmgauwaUid { - //noinspection DuplicatedCode - fn decode(value: SqliteValueRef<'r>) -> Result { - Self::try_from(<&[u8] as Decode>::decode(value)?).map_err(Into::into) - } -} - -impl From<&EmgauwaUid> for Vec { - fn from(uid: &EmgauwaUid) -> Vec { - uid.0.as_bytes().to_vec() - } -} - -impl TryFrom<&str> for EmgauwaUid { - type Error = uuid::Error; - - fn try_from(value: &str) -> Result { - let uuid = Uuid::from_str(value)?; - Ok(Self(uuid)) - } -} - -impl TryFrom<&[u8]> for EmgauwaUid { - type Error = uuid::Error; - - fn try_from(value: &[u8]) -> Result { - Ok(Self(Uuid::from_slice(value)?)) - } -} - -impl From> for EmgauwaUid { - fn from(value: Vec) -> Self { - Self::try_from(value.as_slice()).expect("Failed to parse uid from database") - } -} diff --git a/emgauwa-common/src/types/mod.rs b/emgauwa-common/src/types/mod.rs deleted file mode 100644 index dbbfb77..0000000 --- a/emgauwa-common/src/types/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -mod emgauwa_uid; -mod request; -mod schedule_uid; - -use actix::Message; -pub use emgauwa_uid::EmgauwaUid; -pub use request::*; -pub use schedule_uid::ScheduleUid; -use serde_derive::{Deserialize, Serialize}; - -use crate::db::DbSchedule; -use crate::errors::EmgauwaError; -use crate::models::{Controller, Relay}; - -pub type Weekday = i64; - -pub type RelayStates = Vec>; - -#[derive(Debug, Serialize, Deserialize, Message)] -#[rtype(result = "Result<(), EmgauwaError>")] -pub enum ControllerWsAction { - Register(Controller), - Disconnect, - Schedules(Vec), - Relays(Vec), - Controller(Controller), - RelayStates((EmgauwaUid, RelayStates)), - RelayPulse((i64, Option)), -} diff --git a/emgauwa-common/src/types/request.rs b/emgauwa-common/src/types/request.rs deleted file mode 100644 index 5c9a927..0000000 --- a/emgauwa-common/src/types/request.rs +++ /dev/null @@ -1,95 +0,0 @@ -use serde_derive::{Deserialize, Serialize}; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::db::{DbPeriods, DbSchedule}; -use crate::errors::DatabaseError; -use crate::types::{EmgauwaUid, ScheduleUid}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestScheduleCreate { - pub name: String, - pub periods: DbPeriods, - pub tags: Option>, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestScheduleUpdate { - pub name: Option, - pub periods: Option, - pub tags: Option>, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestRelayUpdate { - pub name: Option, - pub active_schedule: Option, - pub schedules: Option>, - pub tags: Option>, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestRelayPulse { - pub duration: Option, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestScheduleId { - pub id: ScheduleUid, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestControllerUpdate { - pub name: String, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestTagCreate { - pub tag: String, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestMacroActionRelay { - pub number: i64, - pub controller_id: EmgauwaUid, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestMacroActionSchedule { - pub id: ScheduleUid, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestMacroAction { - pub weekday: i64, - pub relay: RequestMacroActionRelay, - pub schedule: RequestMacroActionSchedule, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestMacroCreate { - pub name: String, - pub actions: Vec, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestMacroUpdate { - pub name: Option, - pub actions: Option>, -} - -#[derive(Debug, Deserialize)] -pub struct RequestMacroExecute { - pub weekday: Option, -} - -impl RequestScheduleId { - pub async fn get_schedule( - &self, - conn: &mut PoolConnection, - ) -> Result { - DbSchedule::get_by_uid(conn, &self.id) - .await? - .ok_or(DatabaseError::NotFound) - } -} diff --git a/emgauwa-common/src/types/schedule_uid.rs b/emgauwa-common/src/types/schedule_uid.rs deleted file mode 100644 index b538df9..0000000 --- a/emgauwa-common/src/types/schedule_uid.rs +++ /dev/null @@ -1,171 +0,0 @@ -use std::convert::TryFrom; -use std::fmt::{Debug, Formatter}; -use std::str::FromStr; - -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use sqlx::database::HasArguments; -use sqlx::encode::IsNull; -use sqlx::error::BoxDynError; -use sqlx::sqlite::{SqliteTypeInfo, SqliteValueRef}; -use sqlx::{Decode, Encode, Sqlite, Type}; -use uuid::Uuid; - -#[derive(Clone)] -pub enum ScheduleUid { - Off, - On, - Any(Uuid), -} - -impl ScheduleUid { - const OFF_STR: &'static str = "off"; - const OFF_U128: u128 = 0; - const OFF_U8: u8 = 0; - const ON_STR: &'static str = "on"; - const ON_U128: u128 = 1; - const ON_U8: u8 = 1; -} - -impl Default for ScheduleUid { - fn default() -> Self { - Self::Any(Uuid::new_v4()) - } -} - -impl Debug for ScheduleUid { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - Self::Off => Self::OFF_STR.fmt(f), - Self::On => Self::ON_STR.fmt(f), - Self::Any(value) => value.fmt(f), - } - } -} - -impl PartialEq for ScheduleUid { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::Off, Self::Off) => true, - (Self::On, Self::On) => true, - (Self::Any(my_uuid), Self::Any(other_uuid)) => my_uuid == other_uuid, - _ => false, - } - } -} - -impl Type for ScheduleUid { - fn type_info() -> SqliteTypeInfo { - <&[u8] as Type>::type_info() - } - - fn compatible(ty: &SqliteTypeInfo) -> bool { - <&[u8] as Type>::compatible(ty) - } -} - -impl<'q> Encode<'q, Sqlite> for ScheduleUid { - //noinspection DuplicatedCode - fn encode_by_ref(&self, buf: &mut >::ArgumentBuffer) -> IsNull { - as Encode>::encode(Vec::from(self), buf) - } -} - -impl<'r> Decode<'r, Sqlite> for ScheduleUid { - //noinspection DuplicatedCode - fn decode(value: SqliteValueRef<'r>) -> Result { - Self::try_from(<&[u8] as Decode>::decode(value)?).map_err(Into::into) - } -} - -impl Serialize for ScheduleUid { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - String::from(self).serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for ScheduleUid { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Self::try_from(String::deserialize(deserializer)?.as_str()) - .map_err(|_| serde::de::Error::custom("invalid schedule uid")) - } -} - -impl From for ScheduleUid { - fn from(uid: Uuid) -> Self { - match uid.as_u128() { - Self::OFF_U128 => Self::Off, - Self::ON_U128 => Self::On, - _ => Self::Any(uid), - } - } -} - -impl TryFrom<&str> for ScheduleUid { - type Error = uuid::Error; - - fn try_from(value: &str) -> Result { - match value { - Self::OFF_STR => Ok(Self::Off), - Self::ON_STR => Ok(Self::On), - any => match Uuid::from_str(any) { - Ok(uuid) => Ok(Self::Any(uuid)), - Err(err) => Err(err), - }, - } - } -} - -impl From<&ScheduleUid> for Uuid { - fn from(uid: &ScheduleUid) -> Uuid { - match uid { - ScheduleUid::Off => Uuid::from_u128(ScheduleUid::OFF_U128), - ScheduleUid::On => Uuid::from_u128(ScheduleUid::ON_U128), - ScheduleUid::Any(value) => *value, - } - } -} - -impl From<&ScheduleUid> for String { - fn from(uid: &ScheduleUid) -> String { - match uid { - ScheduleUid::Off => String::from(ScheduleUid::OFF_STR), - ScheduleUid::On => String::from(ScheduleUid::ON_STR), - ScheduleUid::Any(value) => value.as_hyphenated().to_string(), - } - } -} - -impl From<&ScheduleUid> for Vec { - fn from(uid: &ScheduleUid) -> Vec { - match uid { - ScheduleUid::Off => vec![ScheduleUid::OFF_U8], - ScheduleUid::On => vec![ScheduleUid::ON_U8], - ScheduleUid::Any(value) => value.as_bytes().to_vec(), - } - } -} - -impl TryFrom<&[u8]> for ScheduleUid { - type Error = uuid::Error; - - fn try_from(value: &[u8]) -> Result { - let result = match value { - [Self::OFF_U8] => Self::Off, - [Self::ON_U8] => Self::On, - value_bytes => Self::Any(Uuid::from_slice(value_bytes)?), - }; - Ok(result) - } -} - -impl From> for ScheduleUid { - fn from(value: Vec) -> Self { - Self::try_from(value.as_slice()).expect("Failed to parse schedule uid from database") - } -} diff --git a/emgauwa-common/src/utils.rs b/emgauwa-common/src/utils.rs deleted file mode 100644 index 9b2d4ab..0000000 --- a/emgauwa-common/src/utils.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::ffi::CString; -use std::io::{Error, ErrorKind}; -use std::str::FromStr; - -use chrono::Datelike; -use log::LevelFilter; -use simple_logger::SimpleLogger; - -use crate::errors::EmgauwaError; -use crate::settings::Permissions; -use crate::types::{RelayStates, Weekday}; - - -pub fn init_logging(level: &str) -> Result<(), EmgauwaError> { - let log_level: LevelFilter = LevelFilter::from_str(level) - .map_err(|_| EmgauwaError::Other(format!("Invalid log level: {}", level)))?; - log::trace!("Log level set to {:?}", log_level); - - SimpleLogger::new() - .with_level(log_level) - .init() - .map_err(|err| EmgauwaError::Other(format!("Failed to initialize logger: {}", err)))?; - - Ok(()) -} - -// https://blog.lxsang.me/post/id/28.0 -pub fn drop_privileges(permissions: &Permissions) -> Result<(), Error> { - log::info!( - "Dropping privileges to {}:{}", - permissions.user, - permissions.group - ); - - // the group id need to be set first, because, when the user privileges drop, - // we are unable to drop the group privileges - if !permissions.group.is_empty() { - drop_privileges_group(&permissions.group)?; - } - if !permissions.user.is_empty() { - drop_privileges_user(&permissions.user)?; - } - Ok(()) -} - -fn drop_privileges_group(group: &str) -> Result<(), Error> { - // get the gid from username - if let Ok(cstr) = CString::new(group.as_bytes()) { - let p = unsafe { libc::getgrnam(cstr.as_ptr()) }; - if p.is_null() { - return Err(Error::new( - ErrorKind::Other, - format!("Unable to find group: {}", group), - )); - } - if unsafe { libc::setgid((*p).gr_gid) } != 0 { - return Err(Error::new( - ErrorKind::Other, - format!("Unable set gid for group: {}", group), - )); - } - } else { - return Err(Error::new( - ErrorKind::Other, - format!("Cannot create CString from groupname: {}", group), - )); - } - Ok(()) -} - -fn drop_privileges_user(user: &str) -> Result<(), Error> { - // get the uid from username - if let Ok(cstr) = CString::new(user.as_bytes()) { - let p = unsafe { libc::getpwnam(cstr.as_ptr()) }; - if p.is_null() { - return Err(Error::new( - ErrorKind::Other, - format!("Unable to find user: {}", user), - )); - } - if unsafe { libc::setuid((*p).pw_uid) } != 0 { - return Err(Error::new( - ErrorKind::Other, - format!("Unable set uid for user: {}", user), - )); - } - } else { - return Err(Error::new( - ErrorKind::Other, - format!("Cannot create CString from username: {}", user), - )); - } - Ok(()) -} - -pub fn get_weekday() -> Weekday { - (chrono::offset::Local::now() - .date_naive() - .weekday() - .number_from_monday() - - 1) as Weekday -} - -pub fn printable_relay_states(relay_states: &RelayStates) -> String { - let mut relay_debug = String::new(); - relay_states.iter().for_each(|state| { - relay_debug.push_str(match state { - Some(true) => "+", - Some(false) => "-", - None => "?", - }); - }); - relay_debug -} diff --git a/emgauwa-controller/Cargo.toml b/emgauwa-controller/Cargo.toml deleted file mode 100644 index 9947bc5..0000000 --- a/emgauwa-controller/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "emgauwa-controller" -version = "0.5.0" -edition = "2021" -authors = ["Tobias Reisinger "] - -[dependencies] -emgauwa-common = { path = "../emgauwa-common" } - -actix = "0.13" - -tokio = { version = "1.34", features = ["io-std", "macros", "rt-multi-thread"] } -tokio-tungstenite = "0.21" - -simple_logger = "4.3" -log = "0.4" - -chrono = { version = "0.4", features = ["serde"] } -uuid = { version = "1.5", features = ["serde", "v4"] } - -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" - -sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio", "macros", "chrono"] } - -futures = "0.3" -futures-channel = "0.3" - -rppal = "0.17" -rppal-pfd = "0.0.5" -rppal-mcp23s17 = "0.0.3" diff --git a/emgauwa-controller/src/app_state.rs b/emgauwa-controller/src/app_state.rs deleted file mode 100644 index ec9e262..0000000 --- a/emgauwa-controller/src/app_state.rs +++ /dev/null @@ -1,173 +0,0 @@ -use std::sync::Arc; -use std::time::{Duration, Instant}; - -use actix::{Actor, Context, Handler, Message}; -use emgauwa_common::constants; -use emgauwa_common::drivers::RelayDriver; -use emgauwa_common::errors::EmgauwaError; -use emgauwa_common::models::Controller; -use emgauwa_common::types::RelayStates; -use futures::executor::block_on; -use sqlx::{Pool, Sqlite}; -use tokio::sync::Notify; - -use crate::settings::Settings; - -#[derive(Message)] -#[rtype(result = "Result<(), EmgauwaError>")] -pub struct Reload {} - -#[derive(Message)] -#[rtype(result = "()")] -pub struct UpdateRelayStates { - pub relay_states: RelayStates, -} - -#[derive(Message)] -#[rtype(result = "Result<(), EmgauwaError>")] -pub struct RelayPulse { - pub relay_number: i64, - pub duration: Option, -} - -#[derive(Message)] -#[rtype(result = "Controller")] -pub struct GetThis {} - -#[derive(Message)] -#[rtype(result = "Arc")] -pub struct GetControllerNotifier {} - -#[derive(Message)] -#[rtype(result = "Arc")] -pub struct GetRelayNotifier {} - -pub struct AppState { - pub pool: Pool, - pub this: Controller, - pub settings: Settings, - pub drivers: Vec>, - pub controller_notifier: Arc, - pub relay_notifier: Arc, -} - -impl AppState { - pub fn new( - pool: Pool, - this: Controller, - settings: Settings, - drivers: Vec>, - ) -> AppState { - AppState { - pool, - this, - settings, - drivers, - controller_notifier: Arc::new(Notify::new()), - relay_notifier: Arc::new(Notify::new()), - } - } - - pub fn notify_controller_change(&self) { - self.controller_notifier.notify_one(); - } - - pub fn notify_relay_change(&self) { - self.relay_notifier.notify_one(); - } -} - -impl Actor for AppState { - type Context = Context; -} - -impl Handler for AppState { - type Result = Result<(), EmgauwaError>; - - fn handle(&mut self, _msg: Reload, _ctx: &mut Self::Context) -> Self::Result { - log::debug!("Reloading controller"); - let mut pool_conn = block_on(self.pool.acquire())?; - - self.this.reload(&mut pool_conn)?; - - self.notify_controller_change(); - - Ok(()) - } -} - -impl Handler for AppState { - type Result = (); - - fn handle(&mut self, msg: UpdateRelayStates, _ctx: &mut Self::Context) -> Self::Result { - self.this.apply_relay_states(&msg.relay_states); - self.drivers - .iter_mut() - .zip(msg.relay_states.iter()) - .for_each(|(driver, state)| { - if let Err(e) = driver.set(state.unwrap_or(false)) { - log::error!("Error setting relay: {}", e); - } - }); - - self.notify_relay_change(); - } -} - -impl Handler for AppState { - type Result = Result<(), EmgauwaError>; - - fn handle(&mut self, msg: RelayPulse, _ctx: &mut Self::Context) -> Self::Result { - let relay_num = msg.relay_number; - - let duration = Duration::from_secs( - match msg.duration { - None => { - self.settings - .get_relay(relay_num) - .ok_or(EmgauwaError::Other(String::from( - "Relay not found in settings", - )))? - .pulse - } - Some(dur) => Some(dur as u64), - } - .unwrap_or(constants::RELAY_PULSE_DURATION), - ); - let now = Instant::now(); - let until = now + duration; - - self.this.relay_pulse(relay_num, until)?; - log::debug!( - "Pulsing relay {} for {} seconds until {:?}", - relay_num, - duration.as_secs(), - until - ); - Ok(()) - } -} - -impl Handler for AppState { - type Result = Controller; - - fn handle(&mut self, _msg: GetThis, _ctx: &mut Self::Context) -> Self::Result { - self.this.clone() - } -} - -impl Handler for AppState { - type Result = Arc; - - fn handle(&mut self, _msg: GetControllerNotifier, _ctx: &mut Self::Context) -> Self::Result { - Arc::clone(&self.controller_notifier) - } -} - -impl Handler for AppState { - type Result = Arc; - - fn handle(&mut self, _msg: GetRelayNotifier, _ctx: &mut Self::Context) -> Self::Result { - Arc::clone(&self.relay_notifier) - } -} diff --git a/emgauwa-controller/src/driver.rs b/emgauwa-controller/src/driver.rs deleted file mode 100644 index 9df8d31..0000000 --- a/emgauwa-controller/src/driver.rs +++ /dev/null @@ -1,22 +0,0 @@ -use serde::{Deserialize, Deserializer}; - -#[derive(Debug, Clone, Copy)] -pub enum Driver { - Null, - Gpio, - PiFace, -} - -impl<'de> Deserialize<'de> for Driver { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - match String::deserialize(deserializer)?.as_str() { - "null" => Ok(Driver::Null), - "gpio" => Ok(Driver::Gpio), - "piface" => Ok(Driver::PiFace), - _ => Err(serde::de::Error::custom("invalid driver")), - } - } -} diff --git a/emgauwa-controller/src/main.rs b/emgauwa-controller/src/main.rs deleted file mode 100644 index 1ba2d42..0000000 --- a/emgauwa-controller/src/main.rs +++ /dev/null @@ -1,124 +0,0 @@ -use actix::Actor; -use emgauwa_common::db; -use emgauwa_common::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule}; -use emgauwa_common::errors::EmgauwaError; -use emgauwa_common::models::{Controller, FromDbModel}; -use emgauwa_common::types::EmgauwaUid; -use emgauwa_common::utils::{drop_privileges, init_logging}; -use rppal_pfd::PiFaceDigital; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; - -use crate::relay_loop::run_relays_loop; -use crate::settings::Settings; -use crate::ws::run_ws_loop; - -mod app_state; -mod driver; -mod relay_loop; -mod settings; -mod utils; -mod ws; - -async fn create_this_controller( - conn: &mut PoolConnection, - settings: &Settings, -) -> Result { - DbController::create( - conn, - &EmgauwaUid::default(), - &settings.name, - settings.relays.len() as i64, - ) - .await - .map_err(EmgauwaError::from) -} - -async fn create_this_relay( - conn: &mut PoolConnection, - this_controller: &DbController, - settings_relay: &settings::Relay, -) -> Result { - let relay = DbRelay::create( - conn, - &settings_relay.name, - settings_relay.number.ok_or(EmgauwaError::Internal( - "Relay number is missing".to_string(), - ))?, - this_controller, - ) - .await?; - - let off = DbSchedule::get_off(conn).await?; - for weekday in 0..7 { - DbJunctionRelaySchedule::set_schedule(conn, &relay, &off, weekday).await?; - } - - Ok(relay) -} - -#[actix::main] -async fn main() -> Result<(), std::io::Error> { - let settings = settings::init()?; - - drop_privileges(&settings.permissions)?; - - init_logging(&settings.logging.level)?; - - let mut pfd: Option = None; - let drivers = settings.relays_make_drivers(&mut pfd)?; - - let pool = db::init(&settings.database) - .await - .map_err(EmgauwaError::from)?; - - let mut conn = pool.acquire().await.map_err(EmgauwaError::from)?; - - let db_controller = match DbController::get_all(&mut conn) - .await - .map_err(EmgauwaError::from)? - .pop() - { - None => futures::executor::block_on(create_this_controller(&mut conn, &settings))?, - Some(c) => c, - }; - - for relay in &settings.relays { - if DbRelay::get_by_controller_and_num( - &mut conn, - &db_controller, - relay.number.ok_or(EmgauwaError::Internal( - "Relay number is missing".to_string(), - ))?, - ) - .await - .map_err(EmgauwaError::from)? - .is_none() - { - create_this_relay(&mut conn, &db_controller, relay) - .await - .map_err(EmgauwaError::from)?; - } - } - - let db_controller = db_controller - .update(&mut conn, &db_controller.name, settings.relays.len() as i64) - .await - .map_err(EmgauwaError::from)?; - - let this = Controller::from_db_model(&mut conn, db_controller).map_err(EmgauwaError::from)?; - - let url = format!( - "ws://{}:{}/api/v1/ws/controllers", - settings.server.host, settings.server.port - ); - - let app_state = app_state::AppState::new(pool.clone(), this, settings, drivers).start(); - - let _ = tokio::join!( - tokio::spawn(run_relays_loop(app_state.clone())), - tokio::spawn(run_ws_loop(pool.clone(), app_state.clone(), url)), - ); - - Ok(()) -} diff --git a/emgauwa-controller/src/relay_loop.rs b/emgauwa-controller/src/relay_loop.rs deleted file mode 100644 index 3247f7f..0000000 --- a/emgauwa-controller/src/relay_loop.rs +++ /dev/null @@ -1,150 +0,0 @@ -use std::time::{Duration, Instant}; - -use actix::Addr; -use chrono::{Local, Timelike}; -use emgauwa_common::constants::RELAYS_RETRY_TIMEOUT; -use emgauwa_common::errors::EmgauwaError; -use emgauwa_common::models::Controller; -use emgauwa_common::types::{RelayStates, Weekday}; -use emgauwa_common::utils::printable_relay_states; -use futures::pin_mut; -use tokio::time; -use tokio::time::timeout; -use utils::app_state_get_controller_notifier; - -use crate::app_state::AppState; -use crate::utils; - -pub async fn run_relays_loop(app_state: Addr) { - log::debug!("Spawned relays loop"); - loop { - let run_result = run_relays(&app_state).await; - if let Err(err) = run_result { - log::error!("Error running relays: {}", err); - } - time::sleep(RELAYS_RETRY_TIMEOUT).await; - } -} - -async fn run_relays(app_state: &Addr) -> Result<(), EmgauwaError> { - let notifier = &*app_state_get_controller_notifier(app_state).await?; - - let mut last_weekday = emgauwa_common::utils::get_weekday(); - let mut this = utils::app_state_get_this(app_state).await?; - let mut relay_states: RelayStates = Vec::new(); - init_relay_states(&mut relay_states, &this); - calc_relay_states(&mut relay_states, &mut this, app_state).await?; - - let mut duration_override = None; - - loop { - log::debug!( - "Relay loop at {}: {}", - Local::now().naive_local().time(), - printable_relay_states(&this.get_relay_states()) - ); - - let notifier_future = notifier.notified(); - pin_mut!(notifier_future); - let mut changed = timeout( - get_next_duration(&this, &mut duration_override), - &mut notifier_future, - ) - .await - .is_ok(); - - check_weekday(app_state, &mut last_weekday, &mut changed).await?; - - if changed { - log::debug!("Reloading controller in relay loop"); - this = utils::app_state_get_this(app_state).await?; - } - - let now_pulse = Instant::now(); - duration_override = this - .relays - .iter_mut() - .filter_map(|relay| match relay.check_pulsing(&now_pulse) { - None => None, - Some(pulse) => { - let dur = pulse - now_pulse; - log::debug!( - "Pulsing relay {} for {}s until {:?} ", - relay.r.number, - dur.as_secs(), - pulse - ); - Some(dur) - } - }) - .min(); - - calc_relay_states(&mut relay_states, &mut this, app_state).await?; - } -} - -fn init_relay_states(relay_states: &mut RelayStates, this: &Controller) { - relay_states.clear(); - for _ in 0..this.c.relay_count { - relay_states.push(None); - } -} - -async fn calc_relay_states( - relay_states: &mut RelayStates, - this: &mut Controller, - app_state: &Addr, -) -> Result<(), EmgauwaError> { - let now = Local::now().time(); - let now_pulse = Instant::now(); - - this.relays - .iter_mut() - .zip(relay_states.iter_mut()) - .for_each(|(relay, state)| { - relay.is_on = Some( - relay.active_schedule.is_on(&now) || relay.check_pulsing(&now_pulse).is_some(), - ); - *state = relay.is_on; - }); - utils::app_state_update_relays_on(app_state, relay_states.clone()).await -} - -fn get_next_duration(this: &Controller, duration_override: &mut Option) -> Duration { - if let Some(duration) = duration_override { - log::debug!("Duration override. Waiting for {}s", duration.as_secs()); - return *duration; - } - - let now = Local::now().time(); - let now_in_s = now.num_seconds_from_midnight(); - let next_timestamp = this - .get_next_time(&now) - .map_or(86400, |t| t.num_seconds_from_midnight()); - - let duration_to_next = Duration::from_secs((next_timestamp - now_in_s) as u64); - - log::debug!( - "Next timestamp: {}; Waiting for {}s", - next_timestamp, - duration_to_next.as_secs() - ); - - duration_to_next -} - -async fn check_weekday( - app_state: &Addr, - last_weekday: &mut Weekday, - changed: &mut bool, -) -> Result<(), EmgauwaError> { - let current_weekday = emgauwa_common::utils::get_weekday(); - if current_weekday.ne(last_weekday) { - log::debug!("Weekday changed"); - *last_weekday = current_weekday; - utils::app_state_reload(app_state).await?; - *changed = true; - } - - Ok(()) -} diff --git a/emgauwa-controller/src/settings.rs b/emgauwa-controller/src/settings.rs deleted file mode 100644 index 0e6562a..0000000 --- a/emgauwa-controller/src/settings.rs +++ /dev/null @@ -1,106 +0,0 @@ -use emgauwa_common::errors::EmgauwaError; -use emgauwa_common::{drivers, settings}; -use rppal_pfd::PiFaceDigital; -use serde_derive::Deserialize; - -use crate::driver::Driver; - -#[derive(Clone, Debug, Deserialize)] -#[serde(default)] -#[allow(unused)] -pub struct Relay { - pub driver: Driver, - pub name: String, - pub number: Option, - pub pin: u8, - pub inverted: bool, - pub pulse: Option, -} - -#[derive(Clone, Debug, Deserialize)] -#[serde(default)] -#[allow(unused)] -pub struct Settings { - pub server: settings::Server, - pub database: String, - pub permissions: settings::Permissions, - pub logging: settings::Logging, - - pub name: String, - pub relays: Vec, -} - -impl Default for Settings { - fn default() -> Self { - Settings { - server: settings::Server::default(), - database: String::from("sqlite://emgauwa-controller.sqlite"), - permissions: settings::Permissions::default(), - logging: settings::Logging::default(), - - name: String::from("Emgauwa Controller"), - relays: Vec::new(), - } - } -} - -impl Default for Relay { - fn default() -> Self { - Relay { - driver: Driver::Gpio, - number: None, - name: String::from("Relay"), - pin: 0, - inverted: false, - pulse: None, - } - } -} - -pub fn init() -> Result { - let mut settings: Settings = settings::load("controller", "CONTROLLER")?; - - for (num, relay) in settings.relays.iter_mut().enumerate() { - if relay.number.is_none() { - relay.number = Some(num as i64); - } - } - - Ok(settings) -} - -impl Settings { - pub fn get_relay(&self, number: i64) -> Option<&Relay> { - self.relays.iter().find(|r| r.number == Some(number)) - } - - pub fn relays_make_drivers( - &self, - pfd: &mut Option, - ) -> Result>, EmgauwaError> { - let mut drivers = Vec::new(); - for relay in &self.relays { - drivers.push(relay.make_driver(pfd)?); - } - Ok(drivers) - } -} - -impl Relay { - pub fn make_driver( - &self, - pfd: &mut Option, - ) -> Result, EmgauwaError> { - let driver: Box = match self.driver { - Driver::Null => Box::new(drivers::NullDriver::new(self.pin)), - Driver::Gpio => Box::new(drivers::GpioDriver::new(self.pin, self.inverted)?), - Driver::PiFace => { - if pfd.is_none() { - *pfd = Some(drivers::PiFaceDriver::init_piface()?); - } - Box::new(drivers::PiFaceDriver::new(self.pin, pfd)?) - } - }; - Ok(driver) - } -} diff --git a/emgauwa-controller/src/utils.rs b/emgauwa-controller/src/utils.rs deleted file mode 100644 index c6d2830..0000000 --- a/emgauwa-controller/src/utils.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::sync::Arc; - -use actix::Addr; -use emgauwa_common::errors::EmgauwaError; -use emgauwa_common::models::Controller; -use emgauwa_common::types::RelayStates; -use tokio::sync::Notify; - -use crate::app_state; -use crate::app_state::AppState; - -pub async fn app_state_get_this(app_state: &Addr) -> Result { - app_state - .send(app_state::GetThis {}) - .await - .map_err(EmgauwaError::from) -} - -pub async fn app_state_get_relay_notifier( - app_state: &Addr, -) -> Result, EmgauwaError> { - app_state - .send(app_state::GetRelayNotifier {}) - .await - .map_err(EmgauwaError::from) -} - -pub async fn app_state_get_controller_notifier( - app_state: &Addr, -) -> Result, EmgauwaError> { - app_state - .send(app_state::GetControllerNotifier {}) - .await - .map_err(EmgauwaError::from) -} - -pub async fn app_state_reload(app_state: &Addr) -> Result<(), EmgauwaError> { - app_state - .send(app_state::Reload {}) - .await - .map_err(EmgauwaError::from)? -} - -pub async fn app_state_update_relays_on( - app_state: &Addr, - relay_states: RelayStates, -) -> Result<(), EmgauwaError> { - app_state - .send(app_state::UpdateRelayStates { relay_states }) - .await - .map_err(EmgauwaError::from) -} - -pub async fn app_state_relay_pulse( - app_state: &Addr, - relay_number: i64, - duration: Option, -) -> Result<(), EmgauwaError> { - app_state - .send(app_state::RelayPulse { - relay_number, - duration, - }) - .await - .map_err(EmgauwaError::from)? -} diff --git a/emgauwa-controller/src/ws/mod.rs b/emgauwa-controller/src/ws/mod.rs deleted file mode 100644 index 994cec6..0000000 --- a/emgauwa-controller/src/ws/mod.rs +++ /dev/null @@ -1,247 +0,0 @@ -use actix::Addr; -use emgauwa_common::constants::WEBSOCKET_RETRY_TIMEOUT; -use emgauwa_common::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule}; -use emgauwa_common::errors::{DatabaseError, EmgauwaError}; -use emgauwa_common::models::{Controller, Relay}; -use emgauwa_common::types::{ControllerWsAction, ScheduleUid}; -use futures::{future, pin_mut, SinkExt, StreamExt}; -use sqlx::pool::PoolConnection; -use sqlx::{Pool, Sqlite}; -use tokio::time; -use tokio_tungstenite::tungstenite::Message; -use tokio_tungstenite::{connect_async, tungstenite}; - -use crate::app_state::AppState; -use crate::utils; -use crate::utils::{app_state_get_relay_notifier, app_state_get_this}; - -pub async fn run_ws_loop(pool: Pool, app_state: Addr, url: String) { - log::debug!("Spawned ws loop"); - loop { - let run_result = run_websocket(pool.clone(), &app_state, &url).await; - if let Err(err) = run_result { - log::error!("Error running websocket: {}", err); - } - - log::info!( - "Retrying to connect in {} seconds...", - WEBSOCKET_RETRY_TIMEOUT.as_secs() - ); - time::sleep(WEBSOCKET_RETRY_TIMEOUT).await; - } -} - -async fn run_websocket( - pool: Pool, - app_state: &Addr, - url: &str, -) -> Result<(), EmgauwaError> { - log::debug!("Trying to connect to {}", url); - match connect_async(url).await { - Ok(connection) => { - log::info!("Websocket connected"); - let (ws_stream, _) = connection; - - let (mut write, read) = ws_stream.split(); - - let ws_action = ControllerWsAction::Register(app_state_get_this(app_state).await?); - - let ws_action_json = serde_json::to_string(&ws_action)?; - if let Err(err) = write.send(Message::text(ws_action_json)).await { - log::error!("Failed to register at websocket: {}", err); - return Ok(()); - } - - let (app_state_tx, app_state_rx) = futures_channel::mpsc::unbounded::(); - tokio::spawn(read_app_state(app_state.clone(), app_state_tx)); - let app_state_to_ws = app_state_rx.map(Ok).forward(write); - - let read_handler = read.for_each(|msg| handle_message(pool.clone(), app_state, msg)); - - pin_mut!(app_state_to_ws, read_handler); - future::select(app_state_to_ws, read_handler).await; - - log::warn!("Lost connection to websocket"); - } - Err(err) => { - log::warn!("Failed to connect to websocket: {}", err,); - } - } - Ok(()) -} - -async fn read_app_state( - app_state: Addr, - tx: futures_channel::mpsc::UnboundedSender, -) -> Result<(), EmgauwaError> { - let notifier = &*app_state_get_relay_notifier(&app_state).await?; - loop { - notifier.notified().await; - log::debug!("Relay change detected"); - let this = app_state_get_this(&app_state).await?; - let relay_states = this.get_relay_states(); - let ws_action = ControllerWsAction::RelayStates((this.c.uid, relay_states)); - - let ws_action_json = serde_json::to_string(&ws_action)?; - tx.unbounded_send(Message::text(ws_action_json)) - .map_err(|_| { - EmgauwaError::Other(String::from( - "Failed to forward message from app state to websocket", - )) - })?; - } -} - -async fn handle_message( - pool: Pool, - app_state: &Addr, - message_result: Result, -) { - let msg = match message_result { - Ok(msg) => msg, - Err(err) => { - log::error!("Error reading message: {}", err); - return; - } - }; - if let Message::Text(text) = msg { - match serde_json::from_str(&text) { - Ok(action) => { - log::debug!("Received action: {:?}", action); - let mut pool_conn = match pool.acquire().await { - Ok(conn) => conn, - Err(err) => { - log::error!("Failed to acquire database connection: {:?}", err); - return; - } - }; - let action_res = handle_action(&mut pool_conn, app_state, action).await; - if let Err(e) = action_res { - log::error!("Error handling action: {:?}", e); - } - } - Err(e) => { - log::error!("Error deserializing action: {:?}", e); - } - } - } -} - -pub async fn handle_action( - conn: &mut PoolConnection, - app_state: &Addr, - action: ControllerWsAction, -) -> Result<(), EmgauwaError> { - let this = app_state_get_this(app_state).await?; - - match action { - ControllerWsAction::Controller(controller) => { - handle_controller(conn, &this, controller).await? - } - ControllerWsAction::Relays(relays) => handle_relays(conn, &this, relays).await?, - ControllerWsAction::Schedules(schedules) => handle_schedules(conn, schedules).await?, - ControllerWsAction::RelayPulse((relay_num, duration)) => { - handle_relay_pulse(app_state, relay_num, duration).await? - } - _ => return Ok(()), - }; - - utils::app_state_reload(app_state).await -} - -async fn handle_controller( - conn: &mut PoolConnection, - this: &Controller, - controller: Controller, -) -> Result<(), EmgauwaError> { - if controller.c.uid != this.c.uid { - return Err(EmgauwaError::Other(String::from( - "Controller UID mismatch during update", - ))); - } - DbController::get_by_uid(conn, &controller.c.uid) - .await? - .ok_or(DatabaseError::NotFound)? - .update(conn, controller.c.name.as_str(), this.c.relay_count) - .await?; - - Ok(()) -} - -async fn handle_schedules( - conn: &mut PoolConnection, - schedules: Vec, -) -> Result<(), EmgauwaError> { - let mut handled_uids = vec![ - // on and off schedules are always present and should not be updated - ScheduleUid::On, - ScheduleUid::Off, - ]; - for schedule in schedules { - if handled_uids.contains(&schedule.uid) { - continue; - } - handled_uids.push(schedule.uid.clone()); - - log::debug!("Handling schedule: {:?}", schedule); - let schedule_db = DbSchedule::get_by_uid(conn, &schedule.uid).await?; - - if let Some(schedule_db) = schedule_db { - schedule_db - .update(conn, schedule.name.as_str(), &schedule.periods) - .await?; - } else { - DbSchedule::create( - conn, - schedule.uid.clone(), - schedule.name.as_str(), - &schedule.periods, - ) - .await?; - } - } - - Ok(()) -} - -async fn handle_relays( - conn: &mut PoolConnection, - this: &Controller, - relays: Vec, -) -> Result<(), EmgauwaError> { - for relay in relays { - if relay.controller.uid != this.c.uid { - return Err(EmgauwaError::Other(String::from( - "Controller UID mismatch during relay update", - ))); - } - let db_relay = DbRelay::get_by_controller_and_num(conn, &this.c, relay.r.number) - .await? - .ok_or(DatabaseError::NotFound)?; - - db_relay.update(conn, relay.r.name.as_str()).await?; - - handle_schedules(conn, relay.schedules.clone()).await?; - - let mut schedules = Vec::new(); // We need to get the schedules from the database to have the right IDs - for schedule in relay.schedules { - schedules.push( - DbSchedule::get_by_uid(conn, &schedule.uid) - .await? - .ok_or(DatabaseError::NotFound)?, - ); - } - - DbJunctionRelaySchedule::set_schedules(conn, &db_relay, schedules.iter().collect()).await?; - } - - Ok(()) -} - -async fn handle_relay_pulse( - app_state: &Addr, - relay_num: i64, - duration: Option, -) -> Result<(), EmgauwaError> { - utils::app_state_relay_pulse(app_state, relay_num, duration).await -} diff --git a/emgauwa-core/Cargo.toml b/emgauwa-core/Cargo.toml deleted file mode 100644 index 29d5a12..0000000 --- a/emgauwa-core/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "emgauwa-core" -version = "0.5.0" -edition = "2021" -authors = ["Tobias Reisinger "] - -[dependencies] -emgauwa-common = { path = "../emgauwa-common" } - -actix = "0.13" -actix-web = "4.4" -actix-web-actors = "4.2" -actix-cors = "0.7" - -utoipa = "4.2" -utoipa-swagger-ui = { version = "6.0", features = ["actix-web", "debug-embed"] } - -log = "0.4" - -chrono = { version = "0.4", features = ["serde"] } -uuid = { version = "1.5", features = ["serde", "v4"] } -itertools = "0.12" - -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" - -sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio", "macros", "chrono"] } - -futures = "0.3" -tokio = { version = "1.36", features = ["rt", "rt-multi-thread"] } diff --git a/migrations/20231120000000_init.down.sql b/migrations/20231120000000_init.down.sql deleted file mode 100644 index 2547da8..0000000 --- a/migrations/20231120000000_init.down.sql +++ /dev/null @@ -1,8 +0,0 @@ -DROP TABLE macro_actions; -DROP TABLE macros; -DROP TABLE junction_relay_schedule; -DROP TABLE junction_tag; -DROP TABLE tags; -DROP TABLE schedules; -DROP TABLE relays; -DROP TABLE controllers; diff --git a/migrations/20231120000000_init.up.sql b/migrations/20231120000000_init.up.sql deleted file mode 100644 index 6c588eb..0000000 --- a/migrations/20231120000000_init.up.sql +++ /dev/null @@ -1,161 +0,0 @@ -CREATE TABLE controllers -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - uid - BLOB - NOT NULL - UNIQUE, - name - VARCHAR(128) - NOT NULL, - relay_count - INTEGER - NOT NULL, - active - BOOLEAN - NOT NULL - DEFAULT false -); - -CREATE TABLE relays -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - name - VARCHAR(128) - NOT NULL, - number - INTEGER - NOT NULL, - controller_id - INTEGER - NOT NULL - REFERENCES controllers (id) - ON DELETE CASCADE -); - -CREATE TABLE schedules -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - uid - BLOB - NOT NULL - UNIQUE, - name - VARCHAR(128) - NOT NULL, - periods - BLOB - NOT NULL -); - -CREATE TABLE tags -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - tag - VARCHAR(128) - NOT NULL - UNIQUE -); - -CREATE TABLE junction_tag -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - tag_id - INTEGER - NOT NULL - REFERENCES tags (id) - ON DELETE CASCADE, - relay_id - INTEGER - REFERENCES relays (id) - ON DELETE CASCADE, - schedule_id - INTEGER - REFERENCES schedules (id) - ON DELETE CASCADE -); - -CREATE TABLE junction_relay_schedule -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - weekday - SMALLINT - NOT NULL, - relay_id - INTEGER - NOT NULL - REFERENCES relays (id) - ON DELETE CASCADE, - schedule_id - INTEGER - NOT NULL - REFERENCES schedules (id) - ON DELETE SET DEFAULT -); - -CREATE TABLE macros -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - uid - BLOB - NOT NULL - UNIQUE, - name - VARCHAR(128) - NOT NULL -); - -CREATE TABLE macro_actions -( - id - INTEGER - PRIMARY KEY - AUTOINCREMENT - NOT NULL, - macro_id - INTEGER - NOT NULL - REFERENCES macros (id) - ON DELETE CASCADE, - relay_id - INTEGER - NOT NULL - REFERENCES relays (id) - ON DELETE CASCADE, - schedule_id - INTEGER - NOT NULL - REFERENCES schedules (id) - ON DELETE CASCADE, - weekday - SMALLINT - NOT NULL -); diff --git a/emgauwa-core/src/app_state.rs b/src/app_state.rs similarity index 100% rename from emgauwa-core/src/app_state.rs rename to src/app_state.rs diff --git a/emgauwa-core/src/handlers/mod.rs b/src/handlers/mod.rs similarity index 100% rename from emgauwa-core/src/handlers/mod.rs rename to src/handlers/mod.rs diff --git a/emgauwa-core/src/handlers/v1/controllers.rs b/src/handlers/v1/controllers.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/controllers.rs rename to src/handlers/v1/controllers.rs diff --git a/emgauwa-core/src/handlers/v1/macros.rs b/src/handlers/v1/macros.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/macros.rs rename to src/handlers/v1/macros.rs diff --git a/emgauwa-core/src/handlers/v1/mod.rs b/src/handlers/v1/mod.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/mod.rs rename to src/handlers/v1/mod.rs diff --git a/emgauwa-core/src/handlers/v1/relays.rs b/src/handlers/v1/relays.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/relays.rs rename to src/handlers/v1/relays.rs diff --git a/emgauwa-core/src/handlers/v1/schedules.rs b/src/handlers/v1/schedules.rs similarity index 99% rename from emgauwa-core/src/handlers/v1/schedules.rs rename to src/handlers/v1/schedules.rs index 7c8ccc6..8e329a1 100644 --- a/emgauwa-core/src/handlers/v1/schedules.rs +++ b/src/handlers/v1/schedules.rs @@ -171,7 +171,6 @@ pub async fn update( .await??; } - let return_schedule = Schedule::from_db_model(&mut pool_conn, schedule)?; Ok(HttpResponse::Ok().json(return_schedule)) } diff --git a/emgauwa-core/src/handlers/v1/tags.rs b/src/handlers/v1/tags.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/tags.rs rename to src/handlers/v1/tags.rs diff --git a/emgauwa-core/src/handlers/v1/ws/controllers/handlers.rs b/src/handlers/v1/ws/controllers/handlers.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/ws/controllers/handlers.rs rename to src/handlers/v1/ws/controllers/handlers.rs diff --git a/emgauwa-core/src/handlers/v1/ws/controllers/mod.rs b/src/handlers/v1/ws/controllers/mod.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/ws/controllers/mod.rs rename to src/handlers/v1/ws/controllers/mod.rs diff --git a/emgauwa-core/src/handlers/v1/ws/mod.rs b/src/handlers/v1/ws/mod.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/ws/mod.rs rename to src/handlers/v1/ws/mod.rs diff --git a/emgauwa-core/src/handlers/v1/ws/relays/mod.rs b/src/handlers/v1/ws/relays/mod.rs similarity index 100% rename from emgauwa-core/src/handlers/v1/ws/relays/mod.rs rename to src/handlers/v1/ws/relays/mod.rs diff --git a/emgauwa-core/src/main.rs b/src/main.rs similarity index 100% rename from emgauwa-core/src/main.rs rename to src/main.rs diff --git a/emgauwa-core/src/settings.rs b/src/settings.rs similarity index 100% rename from emgauwa-core/src/settings.rs rename to src/settings.rs diff --git a/emgauwa-core/src/utils.rs b/src/utils.rs similarity index 100% rename from emgauwa-core/src/utils.rs rename to src/utils.rs