From 633c3de5bc8539e63f58c1ce84f26c989254828a Mon Sep 17 00:00:00 2001 From: Sina Blattmann Date: Thu, 23 Feb 2023 16:37:14 +0100 Subject: [PATCH 001/114] [WIP] style changes, work on error handling and user feedback --- typescript/Frontend/src/App.tsx | 112 ++++++---- .../Frontend/src/components/CustomerForm.tsx | 19 +- .../src/components/InnovenergyTextfield.tsx | 34 +-- .../{NestedList.tsx => InstallationList.tsx} | 197 +++++++++--------- .../src/components/InstallationTabs.tsx | 73 +++++++ .../src/components/LanguageSelect.tsx | 1 - .../src/components/NavigationButtons.tsx | 35 +++- typescript/Frontend/src/components/Tabs.tsx | 82 -------- .../Frontend/src/components/UserTree.tsx | 5 + typescript/Frontend/src/lang/en.json | 4 +- .../Frontend/src/routes/Installation.tsx | 39 ++-- 11 files changed, 331 insertions(+), 270 deletions(-) rename typescript/Frontend/src/components/{NestedList.tsx => InstallationList.tsx} (90%) create mode 100644 typescript/Frontend/src/components/InstallationTabs.tsx delete mode 100644 typescript/Frontend/src/components/Tabs.tsx create mode 100644 typescript/Frontend/src/components/UserTree.tsx diff --git a/typescript/Frontend/src/App.tsx b/typescript/Frontend/src/App.tsx index 21278ba28..59d9a6a33 100644 --- a/typescript/Frontend/src/App.tsx +++ b/typescript/Frontend/src/App.tsx @@ -1,10 +1,10 @@ import useToken from "./hooks/useToken"; import Login from "./Login"; import { BrowserRouter, Route, Routes } from "react-router-dom"; -import { Box, Grid, Divider } from "@mui/material"; -import NestedList from "./components/NestedList"; +import { Box, Grid, Divider, createTheme, ThemeProvider } from "@mui/material"; +import InstallationList from "./components/InstallationList"; import BasicTable from "./components/Table"; -import BasicTabs from "./components/Tabs"; +import InstallationTabs from "./components/InstallationTabs"; import Alarms from "./routes/Alarms"; import InstallationDetail from "./routes/Installation"; import Log from "./routes/Log"; @@ -13,11 +13,23 @@ import { IntlProvider } from "react-intl"; import { useState } from "react"; import en from "./lang/en.json"; import de from "./lang/de.json"; +import LanguageSelect from "./components/LanguageSelect"; +import LogoutButton from "./components/LogoutButton"; import NavigationButtons from "./components/NavigationButtons"; +import UserList from "./components/UserTree"; const App = () => { const { token, setToken, removeToken } = useToken(); const [language, setLanguage] = useState("en"); + const [currentView, setCurrentView] = useState("installations"); + + const theme = createTheme({ + palette: { + primary: { + main: "#F59100", + }, + }, + }); const getTranslations = () => { if (language === "de") { @@ -32,46 +44,62 @@ const App = () => { return ( - - - - - - - - - - - - - - } - /> - } /> - } /> - } /> - - + + + + + - - + + + + + {currentView === "installations" ? ( + + ) : ( + + )} + + + + + + {currentView === "installations" && ( + <> + + + } + /> + } /> + } + /> + } /> + + + )} + + + + + ); }; diff --git a/typescript/Frontend/src/components/CustomerForm.tsx b/typescript/Frontend/src/components/CustomerForm.tsx index 9c5d70897..eb0d6e3c1 100644 --- a/typescript/Frontend/src/components/CustomerForm.tsx +++ b/typescript/Frontend/src/components/CustomerForm.tsx @@ -1,4 +1,4 @@ -import { Alert, Button, Snackbar } from "@mui/material"; +import { Alert, Button, Grid, InputLabel, Snackbar } from "@mui/material"; import { useFormik } from "formik"; import { useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -92,20 +92,25 @@ const CustomerForm = (props: I_CustomerFormProps) => { value={formik.values.orderNumbers} handleChange={formik.handleChange} /> - + + + - + diff --git a/typescript/Frontend/src/components/InnovenergyTextfield.tsx b/typescript/Frontend/src/components/InnovenergyTextfield.tsx index 6f857db14..0bcd5b57e 100644 --- a/typescript/Frontend/src/components/InnovenergyTextfield.tsx +++ b/typescript/Frontend/src/components/InnovenergyTextfield.tsx @@ -1,4 +1,4 @@ -import { TextField } from "@mui/material"; +import { Grid, InputLabel, TextField } from "@mui/material"; interface I_InnovenergyTextfieldProps { id: string; @@ -7,21 +7,31 @@ interface I_InnovenergyTextfieldProps { name: string; handleChange: (e: React.ChangeEvent) => void; type?: string; + readOnly?: boolean; } const InnovenergyTextfield = (props: I_InnovenergyTextfieldProps) => { return ( - + + + {props.label} + + + + + ); }; diff --git a/typescript/Frontend/src/components/NestedList.tsx b/typescript/Frontend/src/components/InstallationList.tsx similarity index 90% rename from typescript/Frontend/src/components/NestedList.tsx rename to typescript/Frontend/src/components/InstallationList.tsx index d9d25b62c..e3170bfa6 100644 --- a/typescript/Frontend/src/components/NestedList.tsx +++ b/typescript/Frontend/src/components/InstallationList.tsx @@ -1,95 +1,102 @@ -import List from "@mui/material/List"; -import ListItemButton from "@mui/material/ListItemButton"; -import ListItemText from "@mui/material/ListItemText"; -import { Divider, TextField } from "@mui/material"; -import { Link } from "react-router-dom"; -import useRouteMatch from "../hooks/useRouteMatch"; -import routes from "../routes.json"; -import { Fragment, useEffect, useState } from "react"; -import { I_Installation } from "../util/installation.util"; -import axiosConfig from "../config/axiosConfig"; -import { useIntl } from "react-intl"; - -const getPathWithoutId = (path?: string) => { - if (path) { - const splitString = path.split(":"); - return splitString[0]; - } - return routes.installation; -}; - -const filterData = ( - searchQuery: string, - data: I_Installation[] | undefined -) => { - if (data) { - return data.filter( - (installation) => - installation.name.toLowerCase().includes(searchQuery.toLowerCase()) || - installation.location.toLowerCase().includes(searchQuery.toLowerCase()) - ); - } - return data; -}; - -const NestedList = () => { - const [data, setData] = useState(); - const [searchQuery, setSearchQuery] = useState(""); - const intl = useIntl(); - const filteredData = filterData(searchQuery, data); - - const routeMatch = useRouteMatch([ - routes.installationWithId, - routes.alarmsWithId, - routes.usersWithId, - routes.logWithId, - ]); - - useEffect(() => { - console.log("useeffect"); - axiosConfig.get("/GetAllInstallations", {}).then((res) => { - setData(res.data); - }); - }, []); - - return ( - <> - setSearchQuery(e.target.value)} - /> - - {filteredData?.map((installation) => ( - - - - - - - - - ))} - - - ); -}; - -export default NestedList; +import List from "@mui/material/List"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemText from "@mui/material/ListItemText"; +import { Divider, TextField } from "@mui/material"; +import { Link } from "react-router-dom"; +import useRouteMatch from "../hooks/useRouteMatch"; +import routes from "../routes.json"; +import { Fragment, useEffect, useState } from "react"; +import { I_Installation } from "../util/installation.util"; +import axiosConfig from "../config/axiosConfig"; +import { useIntl } from "react-intl"; + +const getPathWithoutId = (path?: string) => { + if (path) { + const splitString = path.split(":"); + return splitString[0]; + } + return routes.installation; +}; + +const filterData = ( + searchQuery: string, + data: I_Installation[] | undefined +) => { + if (data) { + return data.filter( + (installation) => + installation.name.toLowerCase().includes(searchQuery.toLowerCase()) || + installation.location.toLowerCase().includes(searchQuery.toLowerCase()) + ); + } + return data; +}; + +const InstallationList = () => { + const [data, setData] = useState(); + const [searchQuery, setSearchQuery] = useState(""); + const intl = useIntl(); + const filteredData = filterData(searchQuery, data); + + const routeMatch = useRouteMatch([ + routes.installationWithId, + routes.alarmsWithId, + routes.usersWithId, + routes.logWithId, + ]); + + useEffect(() => { + axiosConfig.get("/GetAllInstallations", {}).then((res) => { + setData(res.data); + }); + }, []); + + return ( + <> + setSearchQuery(e.target.value)} + /> + + {filteredData?.map((installation) => ( + + + + + + + + + ))} + + + ); +}; + +export default InstallationList; diff --git a/typescript/Frontend/src/components/InstallationTabs.tsx b/typescript/Frontend/src/components/InstallationTabs.tsx new file mode 100644 index 000000000..8291357ac --- /dev/null +++ b/typescript/Frontend/src/components/InstallationTabs.tsx @@ -0,0 +1,73 @@ +import * as React from "react"; +import Tabs from "@mui/material/Tabs"; +import Tab from "@mui/material/Tab"; +import Box from "@mui/material/Box"; +import { Link } from "react-router-dom"; +import routes from "../routes.json"; +import useRouteMatch from "../hooks/useRouteMatch"; +import { useIntl } from "react-intl"; + +const InstallationTabs = () => { + const routeMatch = useRouteMatch([ + routes.installationWithId, + routes.alarmsWithId, + routes.usersWithId, + routes.logWithId, + ]); + + const id = routeMatch?.params?.id; + const intl = useIntl(); + + if (id) { + return ( + + + + + + + + + + + ); + } + return null; +}; + +export default InstallationTabs; diff --git a/typescript/Frontend/src/components/LanguageSelect.tsx b/typescript/Frontend/src/components/LanguageSelect.tsx index a90217bc4..6349befc0 100644 --- a/typescript/Frontend/src/components/LanguageSelect.tsx +++ b/typescript/Frontend/src/components/LanguageSelect.tsx @@ -13,7 +13,6 @@ const LanguageSelect = (props: LanguageSelectProps) => { value={props.language} label="Age" onChange={(e) => props.setLanguage(e.target.value)} - sx={{ ml: "auto" }} > diff --git a/typescript/Frontend/src/components/NavigationButtons.tsx b/typescript/Frontend/src/components/NavigationButtons.tsx index 9175a7410..21ccbde9a 100644 --- a/typescript/Frontend/src/components/NavigationButtons.tsx +++ b/typescript/Frontend/src/components/NavigationButtons.tsx @@ -1,23 +1,36 @@ -import { Button, ButtonGroup } from "@mui/material"; +import { ToggleButton, ToggleButtonGroup } from "@mui/material"; import { FormattedMessage } from "react-intl"; -const NavigationButtons = () => { +interface NavigationButtonsProps { + currentView: string; + setCurrentView: (value: string) => void; +} +const NavigationButtons = (props: NavigationButtonsProps) => { + const handleChange = ( + event: React.MouseEvent, + newAlignment: string + ) => { + props.setCurrentView(newAlignment); + }; + return ( - - - - + + ); }; diff --git a/typescript/Frontend/src/components/Tabs.tsx b/typescript/Frontend/src/components/Tabs.tsx deleted file mode 100644 index 5d3cadeb0..000000000 --- a/typescript/Frontend/src/components/Tabs.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import * as React from "react"; -import Tabs from "@mui/material/Tabs"; -import Tab from "@mui/material/Tab"; -import Box from "@mui/material/Box"; -import { Link } from "react-router-dom"; -import routes from "../routes.json"; -import useRouteMatch from "../hooks/useRouteMatch"; -import { useIntl } from "react-intl"; -import LogoutButton from "./LogoutButton"; -import LanguageSelect from "./LanguageSelect"; - -interface BasicTabsProps { - removeToken: () => void; - language: string; - setLanguage: (language: string) => void; -} -const BasicTabs = (props: BasicTabsProps) => { - const routeMatch = useRouteMatch([ - routes.installationWithId, - routes.alarmsWithId, - routes.usersWithId, - routes.logWithId, - ]); - - const id = routeMatch?.params?.id; - const intl = useIntl(); - - return ( - - - - - - - - - - - - - ); -}; - -export default BasicTabs; diff --git a/typescript/Frontend/src/components/UserTree.tsx b/typescript/Frontend/src/components/UserTree.tsx new file mode 100644 index 000000000..57cb861c4 --- /dev/null +++ b/typescript/Frontend/src/components/UserTree.tsx @@ -0,0 +1,5 @@ +const UserList = () => { + return
Userlist
; +}; + +export default UserList; diff --git a/typescript/Frontend/src/lang/en.json b/typescript/Frontend/src/lang/en.json index 3197f95b6..8d6940a56 100644 --- a/typescript/Frontend/src/lang/en.json +++ b/typescript/Frontend/src/lang/en.json @@ -2,7 +2,7 @@ "alarms": "Alarms", "allInstallations": "All installations", "applyChanges": "Apply changes", - "country": "country", + "country": "Country", "customerName": "Customer name", "english": "English", "german": "German", @@ -15,4 +15,4 @@ "users": "Users", "logout": "Logout", "updatedSuccessfully": "Updated successfully" -} \ No newline at end of file +} diff --git a/typescript/Frontend/src/routes/Installation.tsx b/typescript/Frontend/src/routes/Installation.tsx index 9e856abf5..8bcd82fed 100644 --- a/typescript/Frontend/src/routes/Installation.tsx +++ b/typescript/Frontend/src/routes/Installation.tsx @@ -13,26 +13,23 @@ const InstallationDetail = () => { const [error, setError] = useState(); useEffect(() => { - setLoading(true); - axiosConfig - .get("/GetInstallationById?id=" + id) - .then((res) => { - setValues(res.data); - setLoading(false); - }) - .catch((err: AxiosError) => { - setError(err); - setLoading(false); - }); + if (id !== "undefined") { + console.log(id); + setLoading(true); + axiosConfig + .get("/GetInstallationById?id=" + id) + .then((res) => { + setValues(res.data); + setLoading(false); + }) + .catch((err: AxiosError) => { + setError(err); + setLoading(false); + }); + } }, [id]); - if (error) { - return ( - - {error.message} - - ); - } else if (values && values.id.toString() === id) { + if (values && values.id && values.id.toString() === id) { return ( @@ -40,6 +37,12 @@ const InstallationDetail = () => { ); } else if (loading) { return ; + } else if (error) { + return ( + + {error.message} + + ); } return null; }; From 8a0308e4414c5f34ef3230c1ac938310c39f011b Mon Sep 17 00:00:00 2001 From: ig Date: Thu, 23 Feb 2023 17:58:33 +0100 Subject: [PATCH 002/114] extract topology related stuff into Topology.cs --- csharp/app/SaliMax/src/Program.cs | 177 +-------------------------- csharp/app/SaliMax/src/Topology.cs | 184 +++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 176 deletions(-) create mode 100644 csharp/app/SaliMax/src/Topology.cs diff --git a/csharp/app/SaliMax/src/Program.cs b/csharp/app/SaliMax/src/Program.cs index 1bbbc8883..e188de1a3 100644 --- a/csharp/app/SaliMax/src/Program.cs +++ b/csharp/app/SaliMax/src/Program.cs @@ -11,13 +11,11 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; using InnovEnergy.Lib.Devices.Ampt; using InnovEnergy.Lib.Devices.Battery48TL; -using InnovEnergy.Lib.Utils; using InnovEnergy.SaliMax.Controller; using InnovEnergy.SaliMax.Log; using InnovEnergy.SaliMax.SaliMaxRelays; using InnovEnergy.SaliMax.SystemConfig; using InnovEnergy.Time.Unix; -using Utils = InnovEnergy.Lib.StatusApi.Utils; #pragma warning disable IL2026 @@ -148,7 +146,7 @@ internal static class Program //JsonSerializer.Serialize(jsonLog, JsonOptions).WriteLine(ConsoleColor.DarkBlue); #endif - PrintTopology(status); + Topology.Print(status); while (UnixTime.Now == t) await Task.Delay(delayTime); @@ -157,181 +155,8 @@ internal static class Program } - private static void PrintTopology(StatusRecord s) - { - const String chargingSeparator = ">>>>>>>>>>"; - const String dischargingSeparator = "<<<<<<<<<"; - const Int32 height = 25; - var pwr = s.InverterStatus!.Ac.ActivePower; - var pvPower = (s.AmptStatus!.Devices[0].Dc.Voltage * s.AmptStatus.Devices[0].Dc.Current + s.AmptStatus!.Devices[1].Dc.Voltage * s.AmptStatus.Devices[1].Dc.Current).Round0(); // TODO using one Ampt - var loadPower = Utils.Round3((s.GridMeterStatus!.ActivePowerL123 + pwr)); // it's a + because the pwr is inverted - - var gridSeparator = s.GridMeterStatus!.ActivePowerL123 > 0 ? chargingSeparator : dischargingSeparator; - var inverterSeparator = -pwr > 0 ? chargingSeparator : dischargingSeparator; - var dcSeparator = -s.DcDcStatus!.Dc.Power > 0 ? chargingSeparator : dischargingSeparator; -#if BatteriesAllowed - var battery1Separator = s.BatteriesStatus[0]!.Power > 0 ? chargingSeparator : dischargingSeparator; - var battery2Separator = s.BatteriesStatus[1]!.Power > 0 ? chargingSeparator : dischargingSeparator; -#endif - - ////////////////// Grid ////////////////////// - var boxGrid = AsciiArt.CreateBox - ( - "Grid", - s.GridMeterStatus.Ac.L1.Voltage.V(), - s.GridMeterStatus.Ac.L2.Voltage.V(), - s.GridMeterStatus.Ac.L3.Voltage.V() - ).AlignCenterVertical(height); - - var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.ActivePowerL123.Round0(), gridSeparator) - .AlignCenterVertical(height); - - - ////////////////// Ac Bus ////////////////////// - var boxAcBus = AsciiArt.CreateBox - ( - "AC Bus", - s.InverterStatus.Ac.L1.Voltage.V(), - s.InverterStatus.Ac.L2.Voltage.V(), - s.InverterStatus.Ac.L3.Voltage.V() - ); - - var boxLoad = AsciiArt.CreateBox - ( - "", - "LOAD", - "" - ); - - var loadRect = CreateRect(boxAcBus, boxLoad, loadPower).AlignBottom(height); - - var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) - .AlignCenterVertical(height); - - //////////////////// Inverter ///////////////////////// - var inverterBox = AsciiArt.CreateBox - ( - "", - "Inverter", - "" - ).AlignCenterVertical(height); - - var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) - .AlignCenterVertical(height); - - - //////////////////// DC Bus ///////////////////////// - var dcBusBox = AsciiArt.CreateBox - ( - "DC Bus", - (s.InverterStatus.ActualDcLinkVoltageLowerHalfExt + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt).V(), - "" - ); - - var pvBox = AsciiArt.CreateBox - ( - "MPPT", - ((s.AmptStatus!.Devices[0].Dc.Voltage + s.AmptStatus!.Devices[1].Dc.Voltage) / 2).Round0().V(), - "" - ); - - var pvRect = CreateRect(pvBox, dcBusBox, pvPower).AlignTop(height); - - var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Dc.Power, dcSeparator) - .AlignCenterVertical(height); - - //////////////////// Dc/Dc ///////////////////////// - var dcBox = AsciiArt.CreateBox - ( - "Dc/Dc", - s.DcDcStatus.BatteryVoltage.V(), - "" - ).AlignCenterVertical(height); -#if BatteriesAllowed - var dcArrow1 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[0]!.Power.Round0(), battery1Separator); - var dcArrow2 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[1]!.Power.Round0(), battery2Separator); -#else - var dcArrow1 =""; - var dcArrow2 = ""; - var dcArrowRect = CreateRect(dcArrow1, dcArrow2).AlignCenterVertical(height); -#endif - - -#if BatteriesAllowed - - //////////////////// Batteries ///////////////////////// - var battery1Box = AsciiArt.CreateBox - ( - "Battery 1", - s.BatteriesStatus[0].Voltage.V(), - s.BatteriesStatus[0].Soc.Percent(), - s.BatteriesStatus[0].Temperature.Celsius() - ); - - var battery2Box = AsciiArt.CreateBox - ( - "Battery 2", - s.BatteriesStatus[1].Voltage.V(), - s.BatteriesStatus[1].Soc.Percent(), - s.BatteriesStatus[1].Temperature.Celsius() - ); - - var batteryRect = CreateRect(battery1Box, battery2Box).AlignCenterVertical(height); - - var avgBatteryBox = AsciiArt.CreateBox - ( - "Batteries", - s.AvgBatteriesStatus!.Voltage.V(), - s.AvgBatteriesStatus.Soc.Percent(), - s.AvgBatteriesStatus.Temperature.Celsius() - ).AlignCenterVertical(height); - - - var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") - .SideBySideWith(loadRect, "") - .SideBySideWith(acBusInvertArrow, "") - .SideBySideWith(inverterBox, "") - .SideBySideWith(inverterArrow, "") - .SideBySideWith(pvRect, "") - .SideBySideWith(dcBusArrow, "") - .SideBySideWith(dcBox, "") - .SideBySideWith(dcArrowRect, "") - .SideBySideWith(batteryRect, "") - .SideBySideWith(avgBatteryBox, "")+ "\n"; -#else - var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") - .SideBySideWith(loadRect, "") - .SideBySideWith(acBusInvertArrow, "") - .SideBySideWith(inverterBox, "") - .SideBySideWith(inverterArrow, "") - .SideBySideWith(pvRect, "") - .SideBySideWith(dcBusArrow, "") - .SideBySideWith(dcBox, "")+ "\n"; -#endif - Console.WriteLine(topology); - } - - private static String CreateRect(String boxTop, String boxBottom, Decimal power) - { - var powerArrow = AsciiArt.CreateVerticalArrow(power); - var boxes = new[] { boxTop, powerArrow, boxBottom }; - var maxWidth = boxes.Max(l => l.Width()); - - var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); - return rect; - } - - private static String CreateRect(String boxTop, String boxBottom) - { - var boxes = new[] { boxTop, boxBottom }; - var maxWidth = boxes.Max(l => l.Width()); - - var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); - return rect; - } - // to delete not used anymore [Conditional("RELEASE")] private static void ReleaseWriteLog(JsonObject jsonLog, UnixTime timestamp) diff --git a/csharp/app/SaliMax/src/Topology.cs b/csharp/app/SaliMax/src/Topology.cs new file mode 100644 index 000000000..e111f8ec4 --- /dev/null +++ b/csharp/app/SaliMax/src/Topology.cs @@ -0,0 +1,184 @@ +using InnovEnergy.Lib.Utils; +using InnovEnergy.SaliMax.Controller; +using InnovEnergy.SaliMax.Log; + +namespace InnovEnergy.SaliMax; + +public static class Topology +{ + public static void Print(StatusRecord s) + { + const String chargingSeparator = ">>>>>>>>>>"; + const String dischargingSeparator = "<<<<<<<<<"; + const Int32 height = 25; + + + var pwr = s.InverterStatus!.Ac.ActivePower; + var pvPower = (s.AmptStatus!.Devices[0].Dc.Voltage * s.AmptStatus.Devices[0].Dc.Current + s.AmptStatus!.Devices[1].Dc.Voltage * s.AmptStatus.Devices[1].Dc.Current).Round0(); // TODO using one Ampt + var loadPower = Utils.Round3((s.GridMeterStatus!.ActivePowerL123 + pwr)); // it's a + because the pwr is inverted + + var gridSeparator = s.GridMeterStatus!.ActivePowerL123 > 0 ? chargingSeparator : dischargingSeparator; + var inverterSeparator = -pwr > 0 ? chargingSeparator : dischargingSeparator; + var dcSeparator = -s.DcDcStatus!.Dc.Power > 0 ? chargingSeparator : dischargingSeparator; +#if BatteriesAllowed + var battery1Separator = s.BatteriesStatus[0]!.Power > 0 ? chargingSeparator : dischargingSeparator; + var battery2Separator = s.BatteriesStatus[1]!.Power > 0 ? chargingSeparator : dischargingSeparator; +#endif + + ////////////////// Grid ////////////////////// + var boxGrid = AsciiArt.CreateBox + ( + "Grid", + s.GridMeterStatus.Ac.L1.Voltage.V(), + s.GridMeterStatus.Ac.L2.Voltage.V(), + s.GridMeterStatus.Ac.L3.Voltage.V() + ).AlignCenterVertical(height); + + var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.ActivePowerL123.Round0(), gridSeparator) + .AlignCenterVertical(height); + + + ////////////////// Ac Bus ////////////////////// + var boxAcBus = AsciiArt.CreateBox + ( + "AC Bus", + s.InverterStatus.Ac.L1.Voltage.V(), + s.InverterStatus.Ac.L2.Voltage.V(), + s.InverterStatus.Ac.L3.Voltage.V() + ); + + var boxLoad = AsciiArt.CreateBox + ( + "", + "LOAD", + "" + ); + + var loadRect = StringUtils.AlignBottom(CreateRect(boxAcBus, boxLoad, loadPower), height); + + var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) + .AlignCenterVertical(height); + + //////////////////// Inverter ///////////////////////// + var inverterBox = AsciiArt.CreateBox + ( + "", + "Inverter", + "" + ).AlignCenterVertical(height); + + var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) + .AlignCenterVertical(height); + + + //////////////////// DC Bus ///////////////////////// + var dcBusBox = AsciiArt.CreateBox + ( + "DC Bus", + (s.InverterStatus.ActualDcLinkVoltageLowerHalfExt + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt).V(), + "" + ); + + var pvBox = AsciiArt.CreateBox + ( + "MPPT", + ((s.AmptStatus!.Devices[0].Dc.Voltage + s.AmptStatus!.Devices[1].Dc.Voltage) / 2).Round0().V(), + "" + ); + + var pvRect = StringUtils.AlignTop(CreateRect(pvBox, dcBusBox, pvPower), height); + + var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Dc.Power, dcSeparator) + .AlignCenterVertical(height); + + //////////////////// Dc/Dc ///////////////////////// + var dcBox = AsciiArt.CreateBox + ( + "Dc/Dc", + s.DcDcStatus.BatteryVoltage.V(), + "" + ).AlignCenterVertical(height); +#if BatteriesAllowed + var dcArrow1 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[0]!.Power.Round0(), battery1Separator); + var dcArrow2 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[1]!.Power.Round0(), battery2Separator); +#else + var dcArrow1 =""; + var dcArrow2 = ""; + var dcArrowRect = StringUtils.AlignCenterVertical(CreateRect(dcArrow1, dcArrow2), height); +#endif + + +#if BatteriesAllowed + + //////////////////// Batteries ///////////////////////// + var battery1Box = AsciiArt.CreateBox + ( + "Battery 1", + s.BatteriesStatus[0].Voltage.V(), + s.BatteriesStatus[0].Soc.Percent(), + s.BatteriesStatus[0].Temperature.Celsius() + ); + + var battery2Box = AsciiArt.CreateBox + ( + "Battery 2", + s.BatteriesStatus[1].Voltage.V(), + s.BatteriesStatus[1].Soc.Percent(), + s.BatteriesStatus[1].Temperature.Celsius() + ); + + var batteryRect = CreateRect(battery1Box, battery2Box).AlignCenterVertical(height); + + var avgBatteryBox = AsciiArt.CreateBox + ( + "Batteries", + s.AvgBatteriesStatus!.Voltage.V(), + s.AvgBatteriesStatus.Soc.Percent(), + s.AvgBatteriesStatus.Temperature.Celsius() + ).AlignCenterVertical(height); + + + var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") + .SideBySideWith(loadRect, "") + .SideBySideWith(acBusInvertArrow, "") + .SideBySideWith(inverterBox, "") + .SideBySideWith(inverterArrow, "") + .SideBySideWith(pvRect, "") + .SideBySideWith(dcBusArrow, "") + .SideBySideWith(dcBox, "") + .SideBySideWith(dcArrowRect, "") + .SideBySideWith(batteryRect, "") + .SideBySideWith(avgBatteryBox, "")+ "\n"; +#else + var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") + .SideBySideWith(loadRect, "") + .SideBySideWith(acBusInvertArrow, "") + .SideBySideWith(inverterBox, "") + .SideBySideWith(inverterArrow, "") + .SideBySideWith(pvRect, "") + .SideBySideWith(dcBusArrow, "") + .SideBySideWith(dcBox, "")+ "\n"; +#endif + Console.WriteLine(topology); + } + + private static String CreateRect(String boxTop, String boxBottom, Decimal power) + { + var powerArrow = AsciiArt.CreateVerticalArrow(power); + var boxes = new[] { boxTop, powerArrow, boxBottom }; + var maxWidth = boxes.Max(l => l.Width()); + + var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); + return rect; + } + + private static String CreateRect(String boxTop, String boxBottom) + { + var boxes = new[] { boxTop, boxBottom }; + var maxWidth = boxes.Max(l => l.Width()); + + var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); + return rect; + } + +} \ No newline at end of file From a7af1c434c43c116145807e939cedf9170c0d60b Mon Sep 17 00:00:00 2001 From: ig Date: Thu, 23 Feb 2023 17:59:55 +0100 Subject: [PATCH 003/114] move undef to Topology.cs --- csharp/app/SaliMax/src/Program.cs | 2 +- csharp/app/SaliMax/src/Topology.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/csharp/app/SaliMax/src/Program.cs b/csharp/app/SaliMax/src/Program.cs index e188de1a3..0734b5b6f 100644 --- a/csharp/app/SaliMax/src/Program.cs +++ b/csharp/app/SaliMax/src/Program.cs @@ -1,4 +1,4 @@ -#undef BatteriesAllowed + using System.Diagnostics; diff --git a/csharp/app/SaliMax/src/Topology.cs b/csharp/app/SaliMax/src/Topology.cs index e111f8ec4..ab8a26ee9 100644 --- a/csharp/app/SaliMax/src/Topology.cs +++ b/csharp/app/SaliMax/src/Topology.cs @@ -1,3 +1,5 @@ +#undef BatteriesAllowed + using InnovEnergy.Lib.Utils; using InnovEnergy.SaliMax.Controller; using InnovEnergy.SaliMax.Log; From 08bd5c31e0f8c5f8718fe9c14a7e8309f9c5b01e Mon Sep 17 00:00:00 2001 From: ig Date: Fri, 24 Feb 2023 09:26:55 +0100 Subject: [PATCH 004/114] remove CsController.csproj --- csharp/InnovEnergy.sln | 7 --- csharp/app/CsController/CsController.csproj | 15 ----- csharp/app/CsController/Program.cs | 62 --------------------- csharp/app/CsController/debug.sh | 21 ------- csharp/app/CsController/service/log/run | 3 - csharp/app/CsController/service/run | 3 - 6 files changed, 111 deletions(-) delete mode 100644 csharp/app/CsController/CsController.csproj delete mode 100644 csharp/app/CsController/Program.cs delete mode 100644 csharp/app/CsController/debug.sh delete mode 100755 csharp/app/CsController/service/log/run delete mode 100755 csharp/app/CsController/service/run diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 9247b7144..69f33a105 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -24,8 +24,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3", "lib/S3/S3.csproj", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deprecated", "deprecated", "{46DE03C4-52D1-47AA-8E60-8BB15361D723}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsController", "app/CsController/CsController.csproj", "{72DBBE42-A09F-43C0-9613-331039857056}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaliMax", "app/SaliMax/SaliMax.csproj", "{25073794-D859-4824-9984-194C7E928496}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusApi", "lib/StatusApi/StatusApi.csproj", "{9D17E78C-8A70-43DB-A619-DC12D20D023D}" @@ -112,10 +110,6 @@ Global {C3639841-13F4-4F24-99C6-7D965593BF89}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3639841-13F4-4F24-99C6-7D965593BF89}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3639841-13F4-4F24-99C6-7D965593BF89}.Release|Any CPU.Build.0 = Release|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Release|Any CPU.Build.0 = Release|Any CPU {25073794-D859-4824-9984-194C7E928496}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25073794-D859-4824-9984-194C7E928496}.Debug|Any CPU.Build.0 = Debug|Any CPU {25073794-D859-4824-9984-194C7E928496}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -195,7 +189,6 @@ Global {E3A5F3A3-72A5-47CC-85C6-2D8E962A0EC1} = {145597B4-3E30-45E6-9F72-4DD43194539A} {46DE03C4-52D1-47AA-8E60-8BB15361D723} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {4A67D79F-F0C9-4BBC-9601-D5948E6C05D3} = {46DE03C4-52D1-47AA-8E60-8BB15361D723} - {72DBBE42-A09F-43C0-9613-331039857056} = {145597B4-3E30-45E6-9F72-4DD43194539A} {25073794-D859-4824-9984-194C7E928496} = {145597B4-3E30-45E6-9F72-4DD43194539A} {9D17E78C-8A70-43DB-A619-DC12D20D023D} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {C3639841-13F4-4F24-99C6-7D965593BF89} = {46DE03C4-52D1-47AA-8E60-8BB15361D723} diff --git a/csharp/app/CsController/CsController.csproj b/csharp/app/CsController/CsController.csproj deleted file mode 100644 index aab629be3..000000000 --- a/csharp/app/CsController/CsController.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - enable - InnovEnergy.CsController - true - - - - - - - - diff --git a/csharp/app/CsController/Program.cs b/csharp/app/CsController/Program.cs deleted file mode 100644 index 4d625c96c..000000000 --- a/csharp/app/CsController/Program.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Reactive.Linq; -using InnovEnergy.Lib.Protocols.DBus; -using InnovEnergy.Lib.Protocols.DBus.Protocol.DataTypes; -using InnovEnergy.Lib.Victron.VeDBus; - - -// dotnet publish EmuMeter.csproj -c Release -r linux-arm -p:PublishSingleFile=true --self-contained true && \ -// rsync -av bin/Release/net6.0/linux-arm/publish/ root@10.2.1.6:/home/root/emu && clear && \ -// ssh root@10.2.1.6 /home/root/emu/EmuMeter - - -Console.WriteLine("Starting CsController "); - -//Enable out InnovEnergy GUI Page through DBusService.DBUS_SERVICE_UNSUPPORTED -// var service = new DBusService("com.victronenergy.unsupported"); -var veProperties = new VeProperties(); -veProperties.Set("/CustomName", "InnovEnergy"); -veProperties.Set("/ProductName", "InnovEnergySW"); - - -var dbus = new DBusConnection(Bus.System); -// var ep = new UnixDomainSocketEndPoint("/home/kim/graber_dbus.sock"); -// var auth = AuthenticationMethod.ExternalAsRoot(); -// var dbusAddress = new Bus(ep, auth); -// var dbus = new DBusConnection(dbusAddress); - - -await veProperties.PublishOnDBus(Bus.System, "com.victronenergy.unsupported"); - -var battery = "com.victronenergy.battery.ttyUSB0"; -var soc = 21.0; - -//TODO change ttyUSB0 for generic Battery on dbus -var names = await dbus.ListNames(); -foreach (var name in names) -{ - if(name.Contains("com.victronenergy.battery.")) - { - battery = name; - break; - } -} - -var mustCharge = dbus - .ObserveSignalMessages(sender: battery, objectPath: "/Soc") - .Select(m => m.Payload)! - .OfType>() - .Where(d => d.ContainsKey("Value")) - .Select(d => d["Value"].Value) - .OfType() - .Do(s => Console.WriteLine($"soc = {s}")) - .Select(d => d < 67) - .DistinctUntilChanged(); - - -mustCharge.Subscribe(b => -{ - dbus.SetValue("com.victronenergy.settings", "/Settings/CGwacs/BatteryLife/State", b ? 9 : 10); // 9 = charge battery, 10 = optimized (no batterylife) -}); - - -// Console.ReadLine(); \ No newline at end of file diff --git a/csharp/app/CsController/debug.sh b/csharp/app/CsController/debug.sh deleted file mode 100644 index 3f25d1795..000000000 --- a/csharp/app/CsController/debug.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -csproj="CsController.csproj" -exe="CsController" -remote="10.2.1.6" -#remote="10.2.2.152" - -netVersion="net6.0" -platform="linux-arm" -config="Release" -host="root@$remote" -dir="/data/innovenergy/$exe" - -set -e - -dotnet publish "$csproj" -c $config -r $platform -p:SuppressTrimmAnalysisWarnings=true -p:PublishSingleFile=true -p:PublishTrimmed=true -p:DebugType=None -p:DebugSymbols=false --self-contained true -rsync -av "bin/$config/$netVersion/$platform/publish/" "$host:$dir" - -clear -ssh "$host" "$dir/$exe" - \ No newline at end of file diff --git a/csharp/app/CsController/service/log/run b/csharp/app/CsController/service/log/run deleted file mode 100755 index d42c9d38b..000000000 --- a/csharp/app/CsController/service/log/run +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -exec 2>&1 -exec multilog t s25000 n4 /var/log/CsController diff --git a/csharp/app/CsController/service/run b/csharp/app/CsController/service/run deleted file mode 100755 index a509d6c68..000000000 --- a/csharp/app/CsController/service/run +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -exec 2>&1 -exec softlimit -d 100000000 -s 1000000 -a 100000000 /opt/innovenergy/CsController/CsController From d2006b52e16b63c35f3193369dd0d8c34c625ecb Mon Sep 17 00:00:00 2001 From: ig Date: Fri, 24 Feb 2023 12:57:51 +0100 Subject: [PATCH 005/114] add ReturnsAttribute to make annotating API more convenient --- .../Backend/Controllers/ReturnsAttribute.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 csharp/app/Backend/Controllers/ReturnsAttribute.cs diff --git a/csharp/app/Backend/Controllers/ReturnsAttribute.cs b/csharp/app/Backend/Controllers/ReturnsAttribute.cs new file mode 100644 index 000000000..6d94088f5 --- /dev/null +++ b/csharp/app/Backend/Controllers/ReturnsAttribute.cs @@ -0,0 +1,22 @@ +using System.Net; +using Microsoft.AspNetCore.Mvc; + +namespace Innovenergy.Backend.Controllers; + +public class ReturnsAttribute : ProducesResponseTypeAttribute +{ + public ReturnsAttribute(HttpStatusCode statusCode) : base((Int32)statusCode) + { + } +} + +public class ReturnsAttribute : ProducesResponseTypeAttribute +{ + public ReturnsAttribute(HttpStatusCode statusCode) : base(typeof(T), (Int32)statusCode) + { + } + + public ReturnsAttribute() : base(typeof(T), (Int32)HttpStatusCode.OK) + { + } +} \ No newline at end of file From c7649dced20f52ab957ce5d5a934f4919921dfeb Mon Sep 17 00:00:00 2001 From: ig Date: Fri, 24 Feb 2023 12:58:47 +0100 Subject: [PATCH 006/114] cleanup Rest API --- csharp/app/Backend/Backend.csproj | 2 + csharp/app/Backend/Controllers/Controller.cs | 311 +++++++++--------- csharp/app/Backend/Controllers/Credentials.cs | 5 +- csharp/app/Backend/Database/Db.cs | 10 +- csharp/app/Backend/Database/Fake.cs | 4 +- csharp/app/Backend/Database/Folder.cs | 15 +- csharp/app/Backend/Database/Installation.cs | 6 +- csharp/app/Backend/Database/User.cs | 79 +++-- csharp/app/Backend/Database/User2Folder.cs | 4 +- .../app/Backend/Database/User2Installation.cs | 4 +- csharp/app/Backend/HeaderFilter.cs | 24 ++ csharp/app/Backend/Model/Folder.cs | 4 +- csharp/app/Backend/Model/Installation.cs | 4 +- .../app/Backend/Model/Relations/Relation.cs | 2 +- csharp/app/Backend/Model/Relations/Session.cs | 2 +- .../Backend/Model/Relations/User2Folder.cs | 2 +- .../Model/Relations/User2Installation.cs | 2 +- csharp/app/Backend/Model/TreeNode.cs | 3 +- csharp/app/Backend/Model/User.cs | 2 +- csharp/app/Backend/Utils/Crypto.cs | 2 +- csharp/app/Backend/Utils/Result.cs | 2 +- csharp/app/Backend/db.sqlite | Bin 290816 -> 290816 bytes csharp/app/Backend/program.cs | 145 +++----- 23 files changed, 319 insertions(+), 315 deletions(-) create mode 100644 csharp/app/Backend/HeaderFilter.cs diff --git a/csharp/app/Backend/Backend.csproj b/csharp/app/Backend/Backend.csproj index c082226db..e6a136cb1 100644 --- a/csharp/app/Backend/Backend.csproj +++ b/csharp/app/Backend/Backend.csproj @@ -4,6 +4,8 @@ net6.0 enable enable + preview + Innovenergy.Backend diff --git a/csharp/app/Backend/Controllers/Controller.cs b/csharp/app/Backend/Controllers/Controller.cs index 32b53084e..10110397e 100644 --- a/csharp/app/Backend/Controllers/Controller.cs +++ b/csharp/app/Backend/Controllers/Controller.cs @@ -1,21 +1,21 @@ using System.Net; using System.Text; -using System.Text.Json; -using Backend.Database; -using Backend.Model; -using Backend.Model.Relations; -using Backend.Utils; +using Innovenergy.Backend.Database; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Model.Relations; +using Innovenergy.Backend.Utils; using Microsoft.AspNetCore.Mvc; using HttpContextAccessor = Microsoft.AspNetCore.Http.HttpContextAccessor; -namespace Backend.Controllers; +namespace Innovenergy.Backend.Controllers; [ApiController] [Route("api/")] public class Controller { - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns] + [Returns(HttpStatusCode.Unauthorized)] + [Returns(HttpStatusCode.BadRequest)] [HttpPost($"{nameof(Login)}")] public Object Login(Credentials credentials) { @@ -29,181 +29,175 @@ public class Controller if (user is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - // if (!VerifyPassword(password, user)) - // return new HttpResponseMessage(HttpStatusCode.Unauthorized); + #if !DEBUG + if (!VerifyPassword(credentials.Password, user)) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + #endif var ses = new Session(user); db.NewSession(ses); return ses.Token; } - private static Boolean VerifyPassword(String password, User user) - { - var pwdBytes = Encoding.UTF8.GetBytes(password); - var saltBytes = Encoding.UTF8.GetBytes(user.Salt + "innovEnergy"); - var pwdHash = Crypto.ComputeHash(pwdBytes, saltBytes); - return user.Password == pwdHash; - } - - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPost($"{nameof(Logout)}")] public Object Logout() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; + var caller = GetCaller(); - if (currentUser is null) - return new HttpResponseMessage(HttpStatusCode.Conflict); + if (caller is null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); - return db.DeleteSession(currentUser.Id); + using var db = Db.Connect(); + return db.DeleteSession(caller.Id); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] - [HttpPost($"{nameof(UpdateS3Creds)}")] - public Object UpdateS3Creds() + + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] + [HttpPost($"{nameof(UpdateS3Credentials)}")] + public Object UpdateS3Credentials() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx!.Items["User"]!; + // TODO: S3Credentials should be per session, not per user - return db.CreateAndSaveUserS3ApiKey(currentUser); + var caller = GetCaller(); + if (caller is null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); + + return db.CreateAndSaveUserS3ApiKey(caller); } - [ProducesResponseType(typeof(User), 200)] - [ProducesResponseType(401)] + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetUserById)}")] public Object GetUserById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - var viewedUser = db.GetUserById(id); - - //using the same error to prevent fishing for ids - if (currentUser == null || viewedUser == null || !db.IsParentOfChild(currentUser, viewedUser)) + var caller = GetCaller(); + if (caller is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); - return viewedUser; + var user = db + .GetDescendantUsers(caller) + .FirstOrDefault(u => u.Id == id); + + return user as Object ?? new HttpResponseMessage(HttpStatusCode.Unauthorized); } - [ProducesResponseType(typeof(Installation), 200)] - [ProducesResponseType(401)] + + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetInstallationById)}")] public Object GetInstallationById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); + var installation = db - .GetAllAccessibleInstallations(currentUser) + .GetAllAccessibleInstallations(caller) .FirstOrDefault(i => i.Id == id); - if (installation is null) - return new HttpResponseMessage(HttpStatusCode.NotFound); - - return installation; + return installation as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound); } - [ProducesResponseType(typeof(Folder), 200)] - [ProducesResponseType(401)] + + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetFolderById)}")] public Object GetFolderById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + if (caller == null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - + var folder = db - .GetAllAccessibleFolders(currentUser!) + .GetAllAccessibleFolders(caller) .FirstOrDefault(f => f.Id == id); - if(folder is null) - return new HttpResponseMessage(HttpStatusCode.NotFound); - - return folder; + return folder as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns] // assuming swagger knows about arrays but not lists (JSON) + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetAllInstallations)}/")] public Object GetAllInstallations() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var user = (User)ctx.Items["User"]; - - if (user == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); - return db.GetAllAccessibleInstallations(user).ToList(); + return db + .GetAllAccessibleInstallations(caller) + .ToList(); // important! } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns] // assuming swagger knows about arrays but not lists (JSON) + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetAllFolders)}/")] public Object GetAllFolders() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - var user = (User)ctx.Items["User"]; - - using var db = Db.Connect(); - - if (user == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - - return db.GetAllAccessibleFolders(user).ToList(); + + using var db = Db.Connect(); + return db + .GetAllAccessibleFolders(caller) + .ToList(); // important! } + - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateUser)}/")] public Object UpdateUser(User updatedUser) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess || !db.IsParentOfChild(currentUser, updatedUser)) + // TODO: distinguish between create and update + + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - return db.GetUserById(updatedUser.Id) != null ? db.UpdateUser(updatedUser) : db.CreateUser(updatedUser); + using var db = Db.Connect(); + + return db.GetUserById(updatedUser.Id) != null + ? db.UpdateUser(updatedUser) + : db.CreateUser(updatedUser); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateInstallation)}/")] public Object UpdateInstallation(Installation updatedInstallation) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess) + if (caller is null || !caller.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - + using var db = Db.Connect(); - var hasAccess = db.GetAllAccessibleInstallations(currentUser) - .Any(i => i.Id == updatedInstallation.Id); - if (!hasAccess) + var hasAccessToInstallation = db + .GetAllAccessibleInstallations(caller) + .Any(i => i.Id == updatedInstallation.Id); + + if (!hasAccessToInstallation) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc @@ -213,64 +207,68 @@ public class Controller } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateFolder)}/")] - public Object UpdateFolder(Folder updatedFolder) + public Object UpdateFolder(Folder folder) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess) + var caller = GetCaller(); + + if (caller is null || !caller.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - var hasAccess = db.GetAllAccessibleFolders(currentUser) - .Any(f => f.Id == updatedFolder.Id); + using var db = Db.Connect(); + + var hasAccessToFolder = db + .GetAllAccessibleFolders(caller) + .Any(f => f.Id == folder.Id); - if (!hasAccess) + if (!hasAccessToFolder) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc // TODO: sanity check changes - return db.UpdateFolder(updatedFolder); + return db.UpdateFolder(folder); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpDelete($"{nameof(DeleteUser)}/")] public Object DeleteUser(Int64 userId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - var userToBeDeleted = db.GetUserById(userId); + var caller = GetCaller(); - if (currentUser == null - || userToBeDeleted == null - || !currentUser.HasWriteAccess - || !db.IsParentOfChild(currentUser,userToBeDeleted)) + if (caller is null || !caller.HasWriteAccess) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); + + var userToBeDeleted = db + .GetDescendantUsers(caller) + .FirstOrDefault(u => u.Id == userId); + + if (userToBeDeleted is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.DeleteUser(userToBeDeleted); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpDelete($"{nameof(DeleteInstallation)}/")] - public Object DeleteInstallation(Int64 idOfInstallationToBeDeleted) + public Object DeleteInstallation(Int64 installationId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + + if (caller is null || !caller.HasWriteAccess) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; var installationToBeDeleted = db - .GetAllAccessibleInstallations(currentUser!) - .FirstOrDefault(i => i.Id == idOfInstallationToBeDeleted); + .GetAllAccessibleInstallations(caller) + .FirstOrDefault(i => i.Id == installationId); if (installationToBeDeleted is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); @@ -278,18 +276,20 @@ public class Controller return db.DeleteInstallation(installationToBeDeleted); } + [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpDelete($"{nameof(DeleteFolder)}/")] public Object DeleteFolder(Int64 folderId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + if (caller == null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; var folderToDelete = db - .GetAllAccessibleFolders(currentUser!) + .GetAllAccessibleFolders(caller) .FirstOrDefault(f => f.Id == folderId); if (folderToDelete is null) @@ -299,5 +299,22 @@ public class Controller } + private static User? GetCaller() + { + var ctxAccessor = new HttpContextAccessor(); + return ctxAccessor.HttpContext?.Items["User"] as User; + } + + private static Boolean VerifyPassword(String password, User user) + { + var pwdBytes = Encoding.UTF8.GetBytes(password); + var saltBytes = Encoding.UTF8.GetBytes(user.Salt + "innovEnergy"); + var pwdHash = Crypto.ComputeHash(pwdBytes, saltBytes); + + return user.Password == pwdHash; + } + } + + diff --git a/csharp/app/Backend/Controllers/Credentials.cs b/csharp/app/Backend/Controllers/Credentials.cs index 43c86a811..2c5c72b45 100644 --- a/csharp/app/Backend/Controllers/Credentials.cs +++ b/csharp/app/Backend/Controllers/Credentials.cs @@ -1,3 +1,6 @@ -namespace Backend.Controllers; +using System.Diagnostics.CodeAnalysis; +namespace Innovenergy.Backend.Controllers; + +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public record Credentials(String Username, String Password); \ No newline at end of file diff --git a/csharp/app/Backend/Database/Db.cs b/csharp/app/Backend/Database/Db.cs index 92d31ca84..aaabfbfd9 100644 --- a/csharp/app/Backend/Database/Db.cs +++ b/csharp/app/Backend/Database/Db.cs @@ -1,11 +1,11 @@ using System.Diagnostics.CodeAnalysis; -using Backend.Model; -using Backend.Model.Relations; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Model.Relations; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db : IDisposable { @@ -97,6 +97,8 @@ public partial class Db : IDisposable return direct.Concat(fromFolders); } + + public IEnumerable GetAllAccessibleFolders(User user) { diff --git a/csharp/app/Backend/Database/Fake.cs b/csharp/app/Backend/Database/Fake.cs index 94325df6d..427c78434 100644 --- a/csharp/app/Backend/Database/Fake.cs +++ b/csharp/app/Backend/Database/Fake.cs @@ -1,6 +1,6 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/Folder.cs b/csharp/app/Backend/Database/Folder.cs index f7411e017..34e20f529 100644 --- a/csharp/app/Backend/Database/Folder.cs +++ b/csharp/app/Backend/Database/Folder.cs @@ -1,9 +1,9 @@ -using Backend.Model; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { @@ -37,6 +37,15 @@ public partial class Db return Installations.Where(f => f.ParentId == parent.Id); } + public IEnumerable GetChildUsers(User parent) + { + return Users.Where(f => f.ParentId == parent.Id); + } + + public IEnumerable GetDescendantUsers(User parent) + { + return parent.Traverse(GetChildUsers); + } public Result CreateFolder(Folder folder) { diff --git a/csharp/app/Backend/Database/Installation.cs b/csharp/app/Backend/Database/Installation.cs index 5473892af..a362a39df 100644 --- a/csharp/app/Backend/Database/Installation.cs +++ b/csharp/app/Backend/Database/Installation.cs @@ -1,8 +1,8 @@ -using Backend.Model; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/User.cs b/csharp/app/Backend/Database/User.cs index cda467968..e002c48be 100644 --- a/csharp/app/Backend/Database/User.cs +++ b/csharp/app/Backend/Database/User.cs @@ -1,18 +1,16 @@ -using System.Net; using System.Net.Mail; using System.Security.Cryptography; using System.Text; -using System.Text.Json; -using Backend.Model; -using Backend.Utils; using Flurl.Http; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; -using Microsoft.AspNetCore.DataProtection; using SQLite; + #pragma warning disable CS0472 #pragma warning disable CS8602 -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { @@ -22,16 +20,16 @@ public partial class Db public User? GetUserById(Int64 id) { - return Users.FirstOrDefault(u => u.Id == id); + return Users.FirstOrDefault(u => u.Id == id); } - + public Boolean IsParentOfChild(User parent, User child) { var parentPointer = child.ParentId; - + if (parent.Id == child.Id) return true; - + while (parentPointer != null && parentPointer != parent.Id) { parentPointer = GetUserById(parentPointer).ParentId; @@ -46,10 +44,10 @@ public partial class Db { if (GetUserByEmail(user.Email) is not null) return Result.Error("User with that email already exists"); - + //Salting and Hashing password var salt = Crypto.GenerateSalt(); - var hashedPassword = Crypto.ComputeHash(Encoding.UTF8.GetBytes(user.Password), + var hashedPassword = Crypto.ComputeHash(Encoding.UTF8.GetBytes(user.Password), Encoding.UTF8.GetBytes(salt + "innovEnergy")); user.Salt = salt; @@ -57,49 +55,51 @@ public partial class Db return Create(user); } - + public Object CreateAndSaveUserS3ApiKey(User user) { //EXOSCALE API URL - const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; + const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0"; const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; var payload = new - { name = user.Email, - operations = new List {"getObject", "listBucket"}, - content = new List{}}; - + { + name = user.Email, + operations = new List { "getObject", "listBucket" }, + content = new List { } + }; + var installationIdList = User2Installation .Where(i => i.UserId == user.Id) .SelectMany(i => Installations.Where(f => i.InstallationId == f.Id)) .ToList(); - + foreach (var installation in installationIdList) { - payload.content.Add(new {domain = "sos", resource_type = "bucket", resource_name = installation.Name}); //TODO CHANGE NAME TO S3BUCKET + payload.content.Add(new { domain = "sos", resource_type = "bucket", resource_name = installation.Name }); //TODO CHANGE NAME TO S3BUCKET } - + using var hmacSha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret)); var signature = Encoding.UTF8 .GetBytes(payload.ToString()) .Apply(hmacSha1.ComputeHash) .Apply(Convert.ToBase64String); - + var keyJson = url .WithHeader("Authorization", $"POST {apiKey};{signature}") .PostJsonAsync(payload) .ReceiveJson() .Result; - + return SetUserS3ApiKey(user, keyJson.GetValue("key")); } - - public Result SetUserS3ApiKey(User user,String key) + + public Result SetUserS3ApiKey(User user, String key) { user.S3Key = key; return Update(user); } - + public Result UpdateUser(User user) { var oldUser = GetUserById(user.Id); @@ -108,42 +108,39 @@ public partial class Db //Checking for unchangeable things // TODO: depends on privileges of caller - - user.Id = oldUser.Id; + + user.Id = oldUser.Id; user.ParentId = oldUser.ParentId; - user.Email = oldUser.Email; - + user.Email = oldUser.Email; + return Update(user); } public Result DeleteUser(User user) { - User2Folder .Delete(u => u.UserId == user.Id); + User2Folder.Delete(u => u.UserId == user.Id); User2Installation.Delete(u => u.UserId == user.Id); - + //Todo check for orphaned Installations/Folders - + // GetChildUsers() - + return Delete(user); } - + // TODO private static Boolean IsValidEmail(String email) { try - { + { var emailAddress = new MailAddress(email); } catch { return false; } + return true; } - - - -} - +} \ No newline at end of file diff --git a/csharp/app/Backend/Database/User2Folder.cs b/csharp/app/Backend/Database/User2Folder.cs index c55458dde..465eea722 100644 --- a/csharp/app/Backend/Database/User2Folder.cs +++ b/csharp/app/Backend/Database/User2Folder.cs @@ -1,7 +1,7 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/User2Installation.cs b/csharp/app/Backend/Database/User2Installation.cs index 79ab547f5..ca329deee 100644 --- a/csharp/app/Backend/Database/User2Installation.cs +++ b/csharp/app/Backend/Database/User2Installation.cs @@ -1,7 +1,7 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/HeaderFilter.cs b/csharp/app/Backend/HeaderFilter.cs new file mode 100644 index 000000000..8ca9cdff8 --- /dev/null +++ b/csharp/app/Backend/HeaderFilter.cs @@ -0,0 +1,24 @@ +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Innovenergy.Backend; + +/// +/// This is for convenient testing! Todo throw me out? +/// Operation filter to add the requirement of the custom header +/// +public class HeaderFilter : IOperationFilter +{ + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + operation.Parameters ??= new List(); + + operation.Parameters.Add(new OpenApiParameter + { + Name = "auth", + In = ParameterLocation.Header, + Content = new Dictionary(), + Required = false + }); + } +} \ No newline at end of file diff --git a/csharp/app/Backend/Model/Folder.cs b/csharp/app/Backend/Model/Folder.cs index fbc016201..c9c39c594 100644 --- a/csharp/app/Backend/Model/Folder.cs +++ b/csharp/app/Backend/Model/Folder.cs @@ -1,6 +1,4 @@ -using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class Folder : TreeNode { diff --git a/csharp/app/Backend/Model/Installation.cs b/csharp/app/Backend/Model/Installation.cs index 9c1f23104..4cca94295 100644 --- a/csharp/app/Backend/Model/Installation.cs +++ b/csharp/app/Backend/Model/Installation.cs @@ -1,6 +1,4 @@ -using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class Installation : TreeNode diff --git a/csharp/app/Backend/Model/Relations/Relation.cs b/csharp/app/Backend/Model/Relations/Relation.cs index 388892872..31250df14 100644 --- a/csharp/app/Backend/Model/Relations/Relation.cs +++ b/csharp/app/Backend/Model/Relations/Relation.cs @@ -1,7 +1,7 @@ using System.Diagnostics.CodeAnalysis; using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; public abstract class Relation { diff --git a/csharp/app/Backend/Model/Relations/Session.cs b/csharp/app/Backend/Model/Relations/Session.cs index 4db1a9188..ff64b6644 100644 --- a/csharp/app/Backend/Model/Relations/Session.cs +++ b/csharp/app/Backend/Model/Relations/Session.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; public class Session : Relation { diff --git a/csharp/app/Backend/Model/Relations/User2Folder.cs b/csharp/app/Backend/Model/Relations/User2Folder.cs index 09d0456bf..6e9f56433 100644 --- a/csharp/app/Backend/Model/Relations/User2Folder.cs +++ b/csharp/app/Backend/Model/Relations/User2Folder.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; internal class User2Folder : Relation { diff --git a/csharp/app/Backend/Model/Relations/User2Installation.cs b/csharp/app/Backend/Model/Relations/User2Installation.cs index 17dd179ab..43fa45d0e 100644 --- a/csharp/app/Backend/Model/Relations/User2Installation.cs +++ b/csharp/app/Backend/Model/Relations/User2Installation.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; internal class User2Installation : Relation { diff --git a/csharp/app/Backend/Model/TreeNode.cs b/csharp/app/Backend/Model/TreeNode.cs index 61eeb2dba..1daf30f74 100644 --- a/csharp/app/Backend/Model/TreeNode.cs +++ b/csharp/app/Backend/Model/TreeNode.cs @@ -1,7 +1,6 @@ using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public abstract class TreeNode { diff --git a/csharp/app/Backend/Model/User.cs b/csharp/app/Backend/Model/User.cs index b9848cc6c..a1a0be392 100644 --- a/csharp/app/Backend/Model/User.cs +++ b/csharp/app/Backend/Model/User.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class User : TreeNode { diff --git a/csharp/app/Backend/Utils/Crypto.cs b/csharp/app/Backend/Utils/Crypto.cs index 57362c5db..199b17fb9 100644 --- a/csharp/app/Backend/Utils/Crypto.cs +++ b/csharp/app/Backend/Utils/Crypto.cs @@ -1,6 +1,6 @@ using System.Security.Cryptography; -namespace Backend.Utils; +namespace Innovenergy.Backend.Utils; public static class Crypto { diff --git a/csharp/app/Backend/Utils/Result.cs b/csharp/app/Backend/Utils/Result.cs index 1db4a4cf4..21e85876c 100644 --- a/csharp/app/Backend/Utils/Result.cs +++ b/csharp/app/Backend/Utils/Result.cs @@ -1,4 +1,4 @@ -namespace Backend.Utils; +namespace Innovenergy.Backend.Utils; public class Result { diff --git a/csharp/app/Backend/db.sqlite b/csharp/app/Backend/db.sqlite index da6dc625ad4a4b6ece95382bb2505180a0801411..fc3ad2ed8207696af0e245f9f64a04984997fcba 100644 GIT binary patch delta 97995 zcma&Pb$k}b7dJXH&+fCnnl6_D)8mQq}t+ zq7jYu5=u3dV>3)W)vFd!n@w!sZ7tPMYgI!}ZKaVE&HJoWW9oSEkxi)N4T)?Gb?=9? zoOeI684dSpm2OOJZ*uA8G|@X*x;G7adQ>(o;}u3Vr?U4-)Kn;GQl>pk@e0edg-*X! zrU9f*bOtrNHqi~Czj@IOpq{JIbEx8FmYoUZ&0^blzm=^|t9Yp~&BKGn1)`>Eq;exk z�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
*NsLaS_WHBl+Dl#fC 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 I!_=n#1Ih?U!~g&Q delta 95238 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 o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); -builder.Services.AddSwaggerGen(config => -{ - config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); - config.OperationFilter(); //Todo testing throw me out -}); - - - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseSwagger(); - app.UseSwaggerUI(cfg => cfg.EnableFilter()); -} - -app.UseCors(); -app.UseHttpsRedirection(); -app.UseAuthorization(); -app.Use(SetSessionUser); -app.MapControllers(); - -app.Run(); - - - - - - -//================= Functions for above =================== - -//Setting User for current Session -async Task SetSessionUser(HttpContext ctx, RequestDelegate next) -{ - var headers = ctx.Request.Headers; - var hasToken = headers.TryGetValue("auth", out var token); - - if (!ctx.Request.Path.ToString().Contains(nameof(Controller.Login))) + public static void Main(string[] args) { - if (!hasToken) + using (var db = Db.Connect()) + db.CreateFakeRelations(); + + var builder = WebApplication.CreateBuilder(args); + + builder.Services.AddControllers(); // TODO: remove magic, specify controllers explicitly + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + + builder.Services.AddHttpContextAccessor(); + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); + builder.Services.AddSwaggerGen(config => { - ctx.Response.StatusCode = 403; - return; - } - - using var db = Db.Connect(); - var user = db.GetUserByToken(token.ToString()); - - if (user is null) - { - ctx.Response.StatusCode = 403; - return; - } - - ctx.Items["User"] = user; - } - - await next(ctx); -} - - - - -/// -/// This is for convenient testing! Todo throw me out? -/// Operation filter to add the requirement of the custom header -/// -public class MyHeaderFilter : IOperationFilter -{ - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - operation.Parameters ??= new List(); - - operation.Parameters.Add(new OpenApiParameter - { - Name = "auth", - In = ParameterLocation.Header, - Content = new Dictionary(), - Required = false + config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); + config.OperationFilter(); //Todo testing throw me out }); + + + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(cfg => cfg.EnableFilter()); + } + + app.UseCors(); + app.UseHttpsRedirection(); + app.UseAuthorization(); + app.Use(SetSessionUser); + app.MapControllers(); + + app.Run(); + } + + private static async Task SetSessionUser(HttpContext ctx, RequestDelegate next) + { + var headers = ctx.Request.Headers; + var hasToken = headers.TryGetValue("auth", out var token); + + if (hasToken) + { + using var db = Db.Connect(); + ctx.Items["User"] = db.GetUserByToken(token.ToString()); + } + + await next(ctx); } } \ No newline at end of file From cc31922ba4a84252055961f568c7598eebb64a21 Mon Sep 17 00:00:00 2001 From: Sina Blattmann Date: Fri, 24 Feb 2023 13:31:53 +0100 Subject: [PATCH 007/114] add loading indicators, clean up code, add user tree prototype --- typescript/Frontend/package-lock.json | 186 ++++++++++++++---- typescript/Frontend/package.json | 1 + typescript/Frontend/src/App.tsx | 113 +++++------ .../Frontend/src/components/CustomerForm.tsx | 4 +- .../src/components/InstallationList.tsx | 98 ++++----- .../Frontend/src/components/Sidebar.tsx | 28 +++ .../Frontend/src/components/UserTree.tsx | 134 ++++++++++++- typescript/Frontend/src/index.tsx | 26 ++- typescript/Frontend/src/routes.json | 19 +- .../Frontend/src/routes/Installation.tsx | 35 ++-- .../util/{installation.util.tsx => types.tsx} | 47 +++-- 11 files changed, 484 insertions(+), 207 deletions(-) create mode 100644 typescript/Frontend/src/components/Sidebar.tsx rename typescript/Frontend/src/util/{installation.util.tsx => types.tsx} (68%) diff --git a/typescript/Frontend/package-lock.json b/typescript/Frontend/package-lock.json index 88944aeda..b3b2c1d8a 100644 --- a/typescript/Frontend/package-lock.json +++ b/typescript/Frontend/package-lock.json @@ -11,6 +11,7 @@ "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@mui/icons-material": "^5.11.0", + "@mui/lab": "^5.0.0-alpha.120", "@mui/material": "^5.11.7", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", @@ -3256,6 +3257,79 @@ } } }, + "node_modules/@mui/lab": { + "version": "5.0.0-alpha.120", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.120.tgz", + "integrity": "sha512-vjlF2jTKSZnNxtUO0xxHEDfpL5cG0LLNRsfKv8TYOiPs0Q1bbqO3YfqJsqxv8yh+wx7EFZc8lwJ4NSAQdenW3A==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@mui/base": "5.0.0-alpha.118", + "@mui/system": "^5.11.9", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.9", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/lab/node_modules/@mui/base": { + "version": "5.0.0-alpha.118", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.118.tgz", + "integrity": "sha512-GAEpqhnuHjRaAZLdxFNuOf2GDTp9sUawM46oHZV4VnYPFjXJDkIYFWfIQLONb0nga92OiqS5DD/scGzVKCL0Mw==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@emotion/is-prop-valid": "^1.2.0", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.9", + "@popperjs/core": "^2.11.6", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/material": { "version": "5.11.8", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.8.tgz", @@ -3301,12 +3375,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.11.7", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.7.tgz", - "integrity": "sha512-XzRTSZdc8bhuUdjablTNv3kFkZ/XIMlKkOqqJCU0G8W3tWGXpau2DXkafPd1ddjPhF9zF3qLKNGgKCChYItjgA==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.9.tgz", + "integrity": "sha512-XMyVIFGomVCmCm92EvYlgq3zrC9K+J6r7IKl/rBJT2/xVYoRY6uM7jeB+Wxh7kXxnW9Dbqsr2yL3cx6wSD1sAg==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@mui/utils": "^5.11.7", + "@babel/runtime": "^7.20.13", + "@mui/utils": "^5.11.9", "prop-types": "^15.8.1" }, "engines": { @@ -3327,11 +3401,11 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.11.8", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.8.tgz", - "integrity": "sha512-iSpZp9AoeictsDi5xAQ4PGXu7mKtQyzMl7ZaWpHIGMFpsNnfY3NQNg+wkj/gpsAZ+Zg+IIyD+t+ig71Kr9fa0w==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.9.tgz", + "integrity": "sha512-bkh2CjHKOMy98HyOc8wQXEZvhOmDa/bhxMUekFX5IG0/w4f5HJ8R6+K6nakUUYNEgjOWPYzNPrvGB8EcGbhahQ==", "dependencies": { - "@babel/runtime": "^7.20.7", + "@babel/runtime": "^7.20.13", "@emotion/cache": "^11.10.5", "csstype": "^3.1.1", "prop-types": "^15.8.1" @@ -3358,15 +3432,15 @@ } }, "node_modules/@mui/system": { - "version": "5.11.8", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.8.tgz", - "integrity": "sha512-zhroUcxAw2x/dISBJKhGbD70DOYCwMFRo7o/LUYTiUfQkfmLhRfEf1bopWgY9nYstn7QOxOq9fA3aR3pHrUTbw==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.9.tgz", + "integrity": "sha512-h6uarf+l3FO6l75Nf7yO+qDGrIoa1DM9nAMCUFZQsNCDKOInRzcptnm8M1w/Z3gVetfeeGoIGAYuYKbft6KZZA==", "dependencies": { - "@babel/runtime": "^7.20.7", - "@mui/private-theming": "^5.11.7", - "@mui/styled-engine": "^5.11.8", + "@babel/runtime": "^7.20.13", + "@mui/private-theming": "^5.11.9", + "@mui/styled-engine": "^5.11.9", "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.7", + "@mui/utils": "^5.11.9", "clsx": "^1.2.1", "csstype": "^3.1.1", "prop-types": "^15.8.1" @@ -3410,11 +3484,11 @@ } }, "node_modules/@mui/utils": { - "version": "5.11.7", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.7.tgz", - "integrity": "sha512-8uyNDeVHZA804Ego20Erv8TpxlbqTe/EbhTI2H1UYr4/RiIbBprat8W4Qqr2UQIsC/b3DLz+0RQ6R/E5BxEcLA==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.9.tgz", + "integrity": "sha512-eOJaqzcEs4qEwolcvFAmXGpln+uvouvOS9FUX6Wkrte+4I8rZbjODOBDVNlK+V6/ziTfD4iNKC0G+KfOTApbqg==", "dependencies": { - "@babel/runtime": "^7.20.7", + "@babel/runtime": "^7.20.13", "@types/prop-types": "^15.7.5", "@types/react-is": "^16.7.1 || ^17.0.0", "prop-types": "^15.8.1", @@ -20422,6 +20496,38 @@ "@babel/runtime": "^7.20.6" } }, + "@mui/lab": { + "version": "5.0.0-alpha.120", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.120.tgz", + "integrity": "sha512-vjlF2jTKSZnNxtUO0xxHEDfpL5cG0LLNRsfKv8TYOiPs0Q1bbqO3YfqJsqxv8yh+wx7EFZc8lwJ4NSAQdenW3A==", + "requires": { + "@babel/runtime": "^7.20.13", + "@mui/base": "5.0.0-alpha.118", + "@mui/system": "^5.11.9", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.9", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "dependencies": { + "@mui/base": { + "version": "5.0.0-alpha.118", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.118.tgz", + "integrity": "sha512-GAEpqhnuHjRaAZLdxFNuOf2GDTp9sUawM46oHZV4VnYPFjXJDkIYFWfIQLONb0nga92OiqS5DD/scGzVKCL0Mw==", + "requires": { + "@babel/runtime": "^7.20.13", + "@emotion/is-prop-valid": "^1.2.0", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.9", + "@popperjs/core": "^2.11.6", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + } + } + } + }, "@mui/material": { "version": "5.11.8", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.8.tgz", @@ -20442,36 +20548,36 @@ } }, "@mui/private-theming": { - "version": "5.11.7", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.7.tgz", - "integrity": "sha512-XzRTSZdc8bhuUdjablTNv3kFkZ/XIMlKkOqqJCU0G8W3tWGXpau2DXkafPd1ddjPhF9zF3qLKNGgKCChYItjgA==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.9.tgz", + "integrity": "sha512-XMyVIFGomVCmCm92EvYlgq3zrC9K+J6r7IKl/rBJT2/xVYoRY6uM7jeB+Wxh7kXxnW9Dbqsr2yL3cx6wSD1sAg==", "requires": { - "@babel/runtime": "^7.20.7", - "@mui/utils": "^5.11.7", + "@babel/runtime": "^7.20.13", + "@mui/utils": "^5.11.9", "prop-types": "^15.8.1" } }, "@mui/styled-engine": { - "version": "5.11.8", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.8.tgz", - "integrity": "sha512-iSpZp9AoeictsDi5xAQ4PGXu7mKtQyzMl7ZaWpHIGMFpsNnfY3NQNg+wkj/gpsAZ+Zg+IIyD+t+ig71Kr9fa0w==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.9.tgz", + "integrity": "sha512-bkh2CjHKOMy98HyOc8wQXEZvhOmDa/bhxMUekFX5IG0/w4f5HJ8R6+K6nakUUYNEgjOWPYzNPrvGB8EcGbhahQ==", "requires": { - "@babel/runtime": "^7.20.7", + "@babel/runtime": "^7.20.13", "@emotion/cache": "^11.10.5", "csstype": "^3.1.1", "prop-types": "^15.8.1" } }, "@mui/system": { - "version": "5.11.8", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.8.tgz", - "integrity": "sha512-zhroUcxAw2x/dISBJKhGbD70DOYCwMFRo7o/LUYTiUfQkfmLhRfEf1bopWgY9nYstn7QOxOq9fA3aR3pHrUTbw==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.9.tgz", + "integrity": "sha512-h6uarf+l3FO6l75Nf7yO+qDGrIoa1DM9nAMCUFZQsNCDKOInRzcptnm8M1w/Z3gVetfeeGoIGAYuYKbft6KZZA==", "requires": { - "@babel/runtime": "^7.20.7", - "@mui/private-theming": "^5.11.7", - "@mui/styled-engine": "^5.11.8", + "@babel/runtime": "^7.20.13", + "@mui/private-theming": "^5.11.9", + "@mui/styled-engine": "^5.11.9", "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.7", + "@mui/utils": "^5.11.9", "clsx": "^1.2.1", "csstype": "^3.1.1", "prop-types": "^15.8.1" @@ -20484,11 +20590,11 @@ "requires": {} }, "@mui/utils": { - "version": "5.11.7", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.7.tgz", - "integrity": "sha512-8uyNDeVHZA804Ego20Erv8TpxlbqTe/EbhTI2H1UYr4/RiIbBprat8W4Qqr2UQIsC/b3DLz+0RQ6R/E5BxEcLA==", + "version": "5.11.9", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.9.tgz", + "integrity": "sha512-eOJaqzcEs4qEwolcvFAmXGpln+uvouvOS9FUX6Wkrte+4I8rZbjODOBDVNlK+V6/ziTfD4iNKC0G+KfOTApbqg==", "requires": { - "@babel/runtime": "^7.20.7", + "@babel/runtime": "^7.20.13", "@types/prop-types": "^15.7.5", "@types/react-is": "^16.7.1 || ^17.0.0", "prop-types": "^15.8.1", diff --git a/typescript/Frontend/package.json b/typescript/Frontend/package.json index b0f0b125f..0d166a2ae 100644 --- a/typescript/Frontend/package.json +++ b/typescript/Frontend/package.json @@ -6,6 +6,7 @@ "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@mui/icons-material": "^5.11.0", + "@mui/lab": "^5.0.0-alpha.120", "@mui/material": "^5.11.7", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", diff --git a/typescript/Frontend/src/App.tsx b/typescript/Frontend/src/App.tsx index 59d9a6a33..711216363 100644 --- a/typescript/Frontend/src/App.tsx +++ b/typescript/Frontend/src/App.tsx @@ -1,8 +1,7 @@ import useToken from "./hooks/useToken"; import Login from "./Login"; import { BrowserRouter, Route, Routes } from "react-router-dom"; -import { Box, Grid, Divider, createTheme, ThemeProvider } from "@mui/material"; -import InstallationList from "./components/InstallationList"; +import { Box, Grid, Divider } from "@mui/material"; import BasicTable from "./components/Table"; import InstallationTabs from "./components/InstallationTabs"; import Alarms from "./routes/Alarms"; @@ -17,20 +16,13 @@ import LanguageSelect from "./components/LanguageSelect"; import LogoutButton from "./components/LogoutButton"; import NavigationButtons from "./components/NavigationButtons"; import UserList from "./components/UserTree"; +import Sidebar from "./components/Sidebar"; const App = () => { const { token, setToken, removeToken } = useToken(); const [language, setLanguage] = useState("en"); const [currentView, setCurrentView] = useState("installations"); - const theme = createTheme({ - palette: { - primary: { - main: "#F59100", - }, - }, - }); - const getTranslations = () => { if (language === "de") { return de; @@ -44,62 +36,53 @@ const App = () => { return ( - - - - - - - - - - - {currentView === "installations" ? ( - - ) : ( - - )} - - - - - - {currentView === "installations" && ( - <> - - - } - /> - } /> - } - /> - } /> - - - )} - + + + + + + + + + + {currentView === "installations" ? : } - - - + + + + + {currentView === "installations" && ( + <> + + + } + /> + } /> + } /> + } /> + + + )} + + + + ); }; diff --git a/typescript/Frontend/src/components/CustomerForm.tsx b/typescript/Frontend/src/components/CustomerForm.tsx index eb0d6e3c1..a5393c71e 100644 --- a/typescript/Frontend/src/components/CustomerForm.tsx +++ b/typescript/Frontend/src/components/CustomerForm.tsx @@ -1,9 +1,9 @@ -import { Alert, Button, Grid, InputLabel, Snackbar } from "@mui/material"; +import { Alert, Button, Grid, Snackbar } from "@mui/material"; import { useFormik } from "formik"; import { useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; import axiosConfig from "../config/axiosConfig"; -import { I_Installation } from "../util/installation.util"; +import { I_Installation } from "../util/types"; import InnovenergyTextfield from "./InnovenergyTextfield"; interface I_CustomerFormProps { diff --git a/typescript/Frontend/src/components/InstallationList.tsx b/typescript/Frontend/src/components/InstallationList.tsx index e3170bfa6..c151fd9aa 100644 --- a/typescript/Frontend/src/components/InstallationList.tsx +++ b/typescript/Frontend/src/components/InstallationList.tsx @@ -1,14 +1,17 @@ import List from "@mui/material/List"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemText from "@mui/material/ListItemText"; -import { Divider, TextField } from "@mui/material"; +import { CircularProgress, Divider, Grid } from "@mui/material"; import { Link } from "react-router-dom"; import useRouteMatch from "../hooks/useRouteMatch"; import routes from "../routes.json"; import { Fragment, useEffect, useState } from "react"; -import { I_Installation } from "../util/installation.util"; +import { I_Installation } from "../util/types"; import axiosConfig from "../config/axiosConfig"; -import { useIntl } from "react-intl"; + +interface InstallationListProps { + searchQuery: string; +} const getPathWithoutId = (path?: string) => { if (path) { @@ -32,11 +35,10 @@ const filterData = ( return data; }; -const InstallationList = () => { +const InstallationList = (props: InstallationListProps) => { const [data, setData] = useState(); - const [searchQuery, setSearchQuery] = useState(""); - const intl = useIntl(); - const filteredData = filterData(searchQuery, data); + const [loading, setLoading] = useState(false); + const filteredData = filterData(props.searchQuery, data); const routeMatch = useRouteMatch([ routes.installationWithId, @@ -46,55 +48,55 @@ const InstallationList = () => { ]); useEffect(() => { + setLoading(true); axiosConfig.get("/GetAllInstallations", {}).then((res) => { setData(res.data); + setLoading(false); }); }, []); return ( <> - setSearchQuery(e.target.value)} - /> - - {filteredData?.map((installation) => ( - - - + + + )} + {data && ( + + {filteredData?.map((installation) => ( + + - - - - - - ))} - + + + + + + + ))} + + )} ); }; diff --git a/typescript/Frontend/src/components/Sidebar.tsx b/typescript/Frontend/src/components/Sidebar.tsx new file mode 100644 index 000000000..00d97c9a3 --- /dev/null +++ b/typescript/Frontend/src/components/Sidebar.tsx @@ -0,0 +1,28 @@ +import { TextField } from "@mui/material"; +import { useState } from "react"; +import { useIntl } from "react-intl"; +import InstallationList from "./InstallationList"; + +const Sidebar = () => { + const [searchQuery, setSearchQuery] = useState(""); + const intl = useIntl(); + + return ( + <> + setSearchQuery(e.target.value)} + /> + + + ); +}; + +export default Sidebar; diff --git a/typescript/Frontend/src/components/UserTree.tsx b/typescript/Frontend/src/components/UserTree.tsx index 57cb861c4..219b2e8ca 100644 --- a/typescript/Frontend/src/components/UserTree.tsx +++ b/typescript/Frontend/src/components/UserTree.tsx @@ -1,5 +1,137 @@ +import TreeView from "@mui/lab/TreeView"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import ChevronRightIcon from "@mui/icons-material/ChevronRight"; +import { ReactNode } from "react"; +import { TreeItem } from "@mui/lab"; +import { I_Folder, I_Installation } from "../util/types"; const UserList = () => { - return
Userlist
; + const data: I_Folder[] = [ + { + id: 107, + name: "Bruen-Tromp", + information: "05 Burrows Terrace", + parentId: 75, + type: "Folder", + children: [ + { + id: 100, + name: "Sporer and Sons", + information: "820 Helena Terrace", + parentId: 107, + type: "Folder", + }, + { + id: 101, + name: "Hahn-Heaney", + information: "144 Di Loreto Center", + parentId: 107, + type: "Folder", + }, + ], + }, + { + id: 125, + name: "Sporer and Sons", + information: "820 Helena Terrace", + parentId: 107, + type: "Folder", + children: [ + { + location: "Säffle", + region: "SG", + country: "SE", + orderNumbers: "1LWDGmdXCLmCRFJHTKwcmpoP7bcNeaWJuj", + lat: 0, + long: 0, + s3Bucket: "", + id: 632, + name: "Nikolas Scholz", + information: "", + parentId: 125, + type: "Installation", + }, + { + location: "Krasnoye", + region: "ZH", + country: "RU", + orderNumbers: "1M4Rw8toMSJn3d8ULouDd1gYKzANFXeMWh", + lat: 0, + long: 0, + s3Bucket: "", + id: 248, + name: "Judye Goldson", + information: "", + parentId: 125, + type: "Installation", + }, + { + id: 103, + name: "Bruen-Tromp", + information: "05 Burrows Terrace", + parentId: 75, + type: "Folder", + children: [ + { + id: 100, + name: "Sporer and Sons", + information: "820 Helena Terrace", + parentId: 107, + type: "Folder", + }, + { + id: 101, + name: "Hahn-Heaney", + information: "144 Di Loreto Center", + parentId: 107, + type: "Folder", + }, + ], + }, + ], + }, + { + id: 135, + name: "Hahn-Heaney", + information: "144 Di Loreto Center", + parentId: 107, + type: "Folder", + }, + ]; + + const instanceOfFolder = (object: any): object is I_Folder => { + return "children" in object; + }; + + const getNodes = (element: I_Folder | I_Installation): null | ReactNode => { + if (instanceOfFolder(element)) { + return element.children ? renderTree(element.children) : null; + } + return null; + }; + + const renderTree = (data: (I_Folder | I_Installation)[]): ReactNode => { + return data.map((element) => { + return ( + + {getNodes(element)} + + ); + }); + }; + return ( + } + defaultExpandIcon={} + sx={{ height: 300, flexGrow: 1, maxWidth: 400 }} + > + {renderTree(data)} + + ); }; export default UserList; diff --git a/typescript/Frontend/src/index.tsx b/typescript/Frontend/src/index.tsx index 7d6aef251..c8c69e581 100644 --- a/typescript/Frontend/src/index.tsx +++ b/typescript/Frontend/src/index.tsx @@ -1,16 +1,28 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from "react"; +import ReactDOM from "react-dom/client"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; +import { createTheme, ThemeProvider } from "@mui/material"; const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById("root") as HTMLElement ); + +const theme = createTheme({ + palette: { + primary: { + main: "#F59100", + }, + }, +}); + root.render( + - , + + ); // If you want to start measuring performance in your app, pass a function diff --git a/typescript/Frontend/src/routes.json b/typescript/Frontend/src/routes.json index 5105d9474..311ef8a1c 100644 --- a/typescript/Frontend/src/routes.json +++ b/typescript/Frontend/src/routes.json @@ -1,10 +1,11 @@ { - "installationWithId": "/installation/:id", - "installation": "/installation/", - "alarmsWithId": "/alarms/:id", - "alarms": "/alarms/", - "usersWithId":"/users/:id", - "users":"/users/", - "logWithId": "/log/:id", - "log": "/log/" -} \ No newline at end of file + "installationWithId": "/installation/:id", + "installation": "/installation/", + "alarmsWithId": "/alarms/:id", + "alarms": "/alarms/", + "usersWithId": "/users/:id", + "users": "/users/", + "logWithId": "/log/:id", + "log": "/log/", + "installations": "/installations" +} diff --git a/typescript/Frontend/src/routes/Installation.tsx b/typescript/Frontend/src/routes/Installation.tsx index 8bcd82fed..675d65ca7 100644 --- a/typescript/Frontend/src/routes/Installation.tsx +++ b/typescript/Frontend/src/routes/Installation.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import CustomerForm from "../components/CustomerForm"; import axiosConfig from "../config/axiosConfig"; -import { I_Installation } from "../util/installation.util"; +import { I_Installation } from "../util/types"; const InstallationDetail = () => { const { id } = useParams(); @@ -13,20 +13,17 @@ const InstallationDetail = () => { const [error, setError] = useState(); useEffect(() => { - if (id !== "undefined") { - console.log(id); - setLoading(true); - axiosConfig - .get("/GetInstallationById?id=" + id) - .then((res) => { - setValues(res.data); - setLoading(false); - }) - .catch((err: AxiosError) => { - setError(err); - setLoading(false); - }); - } + setLoading(true); + axiosConfig + .get("/GetInstallationById?id=" + id) + .then((res) => { + setValues(res.data); + setLoading(false); + }) + .catch((err: AxiosError) => { + setError(err); + setLoading(false); + }); }, [id]); if (values && values.id && values.id.toString() === id) { @@ -36,7 +33,13 @@ const InstallationDetail = () => { ); } else if (loading) { - return ; + return ( + + + + ); } else if (error) { return ( diff --git a/typescript/Frontend/src/util/installation.util.tsx b/typescript/Frontend/src/util/types.tsx similarity index 68% rename from typescript/Frontend/src/util/installation.util.tsx rename to typescript/Frontend/src/util/types.tsx index 7f35e1ebd..d77743e4a 100644 --- a/typescript/Frontend/src/util/installation.util.tsx +++ b/typescript/Frontend/src/util/types.tsx @@ -1,19 +1,28 @@ -// TODO add if required or not -export interface I_Installation { - type: string; - title: string; - status: number; - detail: string; - instance: string; - location: string; - region: string; - country: string; - orderNumbers: string; - lat: number; - long: number; - s3Bucket: string; - id: number; - name: string; - information: string; - parentId: number; -} +// TODO add if required or not +export interface I_Installation { + type: string; + title: string; + status: number; + detail: string; + instance: string; + location: string; + region: string; + country: string; + orderNumbers: string; + lat: number; + long: number; + s3Bucket: string; + id: number; + name: string; + information: string; + parentId: number; +} + +export interface I_Folder { + id: number; + name: string; + information: string; + parentId: number; + type: string; + children?: (I_Installation | I_Folder)[]; +} From 599b23da2cb5d12333cfe8432110cbbe4f05d142 Mon Sep 17 00:00:00 2001 From: ig Date: Fri, 24 Feb 2023 13:59:56 +0100 Subject: [PATCH 008/114] add GetTree endpoint --- csharp/app/Backend/Controllers/Controller.cs | 47 +++++++++++++++++-- csharp/app/Backend/Model/TreeNode.Equality.cs | 24 ++++++++++ csharp/app/Backend/Model/TreeNode.cs | 23 ++------- csharp/app/Backend/{program.cs => Program.cs} | 11 +++-- 4 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 csharp/app/Backend/Model/TreeNode.Equality.cs rename csharp/app/Backend/{program.cs => Program.cs} (81%) diff --git a/csharp/app/Backend/Controllers/Controller.cs b/csharp/app/Backend/Controllers/Controller.cs index 10110397e..345ac4e58 100644 --- a/csharp/app/Backend/Controllers/Controller.cs +++ b/csharp/app/Backend/Controllers/Controller.cs @@ -160,8 +160,47 @@ public class Controller .GetAllAccessibleFolders(caller) .ToList(); // important! } - + [Returns] // assuming swagger knows about arrays but not lists (JSON) + [Returns(HttpStatusCode.Unauthorized)] + [HttpGet($"{nameof(GetTree)}/")] + public Object GetTree() + { + var caller = GetCaller(); + if (caller == null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); + + var folders = db + .GetDirectlyAccessibleFolders(caller) // ReSharper disable once AccessToDisposedClosure + .Select(f => PopulateChildren(db, f)); + + var installations = db.GetDirectlyAccessibleInstallations(caller); + + return folders + .Concat(installations) + .ToList(); // important! + } + + private static Folder PopulateChildren(Db db, Folder folder, HashSet? hs = null) + { + // TODO: remove cycle detector + hs ??= new HashSet(); + if (!hs.Add(folder.Id)) + throw new Exception("Cycle detected: folder " + folder.Id); + + var installations = db.GetChildInstallations(folder); + var folders = db + .GetChildFolders(folder) + .Select(c => PopulateChildren(db, c, hs)); + + folder.Children = folders.Concat(installations).ToList(); + + return folder; + } + + [Returns(HttpStatusCode.OK)] [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateUser)}/")] @@ -184,7 +223,7 @@ public class Controller [Returns(HttpStatusCode.OK)] [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateInstallation)}/")] - public Object UpdateInstallation(Installation updatedInstallation) + public Object UpdateInstallation(Installation installation) { var caller = GetCaller(); @@ -195,7 +234,7 @@ public class Controller var hasAccessToInstallation = db .GetAllAccessibleInstallations(caller) - .Any(i => i.Id == updatedInstallation.Id); + .Any(i => i.Id == installation.Id); if (!hasAccessToInstallation) return new HttpResponseMessage(HttpStatusCode.Unauthorized); @@ -203,7 +242,7 @@ public class Controller // TODO: accessibility by other users etc // TODO: sanity check changes - return db.UpdateInstallation(updatedInstallation); + return db.UpdateInstallation(installation); } diff --git a/csharp/app/Backend/Model/TreeNode.Equality.cs b/csharp/app/Backend/Model/TreeNode.Equality.cs new file mode 100644 index 000000000..b044a020f --- /dev/null +++ b/csharp/app/Backend/Model/TreeNode.Equality.cs @@ -0,0 +1,24 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Innovenergy.Backend.Model; + +public abstract partial class TreeNode +{ + protected Boolean Equals(TreeNode other) + { + return Id == other.Id && ParentId == other.ParentId; + } + + public override Boolean Equals(Object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((TreeNode)obj); + } + + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] + public override Int32 GetHashCode() + { + return HashCode.Combine(Id, ParentId); + } +} \ No newline at end of file diff --git a/csharp/app/Backend/Model/TreeNode.cs b/csharp/app/Backend/Model/TreeNode.cs index 1daf30f74..b3cf22170 100644 --- a/csharp/app/Backend/Model/TreeNode.cs +++ b/csharp/app/Backend/Model/TreeNode.cs @@ -2,33 +2,20 @@ using SQLite; namespace Innovenergy.Backend.Model; -public abstract class TreeNode +public abstract partial class TreeNode { [PrimaryKey, AutoIncrement] public Int64 Id { get; set; } public String Name { get; set; } = ""; public String Information { get; set; } = ""; // unstructured random info - protected Boolean Equals(TreeNode other) - { - return Id == other.Id && ParentId == other.ParentId; - } - - public override Boolean Equals(Object? obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - return obj.GetType() == this.GetType() && Equals((TreeNode)obj); - } - - public override Int32 GetHashCode() - { - return HashCode.Combine(Id, ParentId); - } - [Indexed] // parent/child relation public Int64 ParentId { get; set; } [Ignore] // not in DB, can be used in typescript as type discriminator public String Type => GetType().Name; + + [Ignore] + public IReadOnlyList? Children { get; set; } + } \ No newline at end of file diff --git a/csharp/app/Backend/program.cs b/csharp/app/Backend/Program.cs similarity index 81% rename from csharp/app/Backend/program.cs rename to csharp/app/Backend/Program.cs index 26c44b71c..fd0206737 100644 --- a/csharp/app/Backend/program.cs +++ b/csharp/app/Backend/Program.cs @@ -3,9 +3,9 @@ using Microsoft.OpenApi.Models; namespace Innovenergy.Backend; -public class Program +public static class Program { - public static void Main(string[] args) + public static void Main(String[] args) { using (var db = Db.Connect()) db.CreateFakeRelations(); @@ -18,10 +18,11 @@ public class Program builder.Services.AddHttpContextAccessor(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); - builder.Services.AddSwaggerGen(config => + builder.Services.AddSwaggerGen(c => { - config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); - config.OperationFilter(); //Todo testing throw me out + c.SwaggerDoc("v1", new OpenApiInfo { Title = "InnovEnergy Backend API", Version = "v1" }); + c.UseAllOfToExtendReferenceSchemas(); + c.OperationFilter(); //Todo testing throw me out }); From 955b0e7118ed218911dcff6875773cbe151eaa44 Mon Sep 17 00:00:00 2001 From: ig Date: Sat, 25 Feb 2023 15:53:58 +0100 Subject: [PATCH 009/114] tie namespace and assembly names to directory structure --- csharp/InnovEnergy.props | 5 +-- csharp/InnovEnergy.sln | 2 +- csharp/app/Backend/Backend.csproj | 20 ++--------- csharp/app/BmsTunnel/BatteryConnection.cs | 4 +-- csharp/app/BmsTunnel/BmsTunnel.cs | 2 +- csharp/app/BmsTunnel/BmsTunnel.csproj | 4 --- csharp/app/BmsTunnel/CliPrograms.cs | 2 +- csharp/app/BmsTunnel/Program.cs | 2 +- csharp/app/Collector/Collector.csproj | 4 --- csharp/app/Collector/src/BatteryDataParser.cs | 8 ++--- .../app/Collector/src/BatteryDataParserV4.cs | 8 ++--- .../Collector/src/Influx/FieldAttribute.cs | 2 +- .../app/Collector/src/Influx/InfluxRecord.cs | 6 ++-- .../src/Influx/LineProtocolSyntax.cs | 2 +- .../app/Collector/src/Influx/TagAttribute.cs | 2 +- csharp/app/Collector/src/Program.cs | 12 +++---- csharp/app/Collector/src/Records/Alarms.cs | 4 +-- .../Collector/src/Records/BatteryRecord.cs | 2 +- .../Collector/src/Records/BatteryStatus.cs | 4 +-- csharp/app/Collector/src/Records/Error.cs | 4 +-- .../src/Records/InstallationStatus.cs | 4 +-- csharp/app/Collector/src/Records/IoStatus.cs | 4 +-- csharp/app/Collector/src/Records/Leds.cs | 4 +-- .../app/Collector/src/Records/Temperatures.cs | 5 ++- csharp/app/Collector/src/Records/Warnings.cs | 5 ++- csharp/app/Collector/src/Settings.cs | 2 +- csharp/app/Collector/src/Utils/Extensions.cs | 2 +- csharp/app/Collector/src/Utils/Log.cs | 2 +- csharp/app/Collector/src/Utils/Property.cs | 2 +- .../src/Utils/ReadOnlyListExtensions.cs | 2 +- csharp/app/Collector/src/Utils/Utils.cs | 2 +- csharp/app/EmuMeterDriver/Config.cs | 2 +- csharp/app/EmuMeterDriver/EmuMeterDriver.cs | 3 +- .../app/EmuMeterDriver/EmuMeterDriver.csproj | 4 --- csharp/app/EmuMeterDriver/Nic.cs | 2 +- csharp/app/EmuMeterDriver/Program.cs | 2 +- csharp/app/EmuMeterDriver/Signal.cs | 2 +- csharp/app/EmuMeterDriver/Utils.cs | 2 +- csharp/app/InnovEnergy.app.props | 2 +- csharp/app/OpenVpnCertificatesServer/Files.cs | 4 +-- csharp/app/OpenVpnCertificatesServer/Http.cs | 5 ++- .../OpenVpnCertificatesServer.csproj | 4 --- .../PKI/CertificateAuthority.cs | 2 +- .../app/OpenVpnCertificatesServer/PKI/Pem.cs | 2 +- .../PKI/PwdFinder.cs | 2 +- .../app/OpenVpnCertificatesServer/Program.cs | 13 ++++--- csharp/app/OpenVpnCertificatesServer/Utils.cs | 5 ++- csharp/app/RemoteSupportConsole/Login.cs | 2 +- .../ObservablePipeSource.cs | 2 +- csharp/app/RemoteSupportConsole/Program.cs | 2 +- .../RemoteSupportConsole.csproj | 4 --- csharp/app/RemoteSupportConsole/Ssh.cs | 2 +- .../app/RemoteSupportConsole/VpnConnection.cs | 2 +- csharp/app/RemoteSupportConsole/VpnInfo.cs | 2 +- .../app/RemoteSupportConsole/VrmConnection.cs | 2 +- csharp/app/RemoteSupportConsole/VrmInfo.cs | 2 +- csharp/app/RemoteSupportConsole/VrmProxy.cs | 2 +- csharp/app/SaliMax/SaliMax.csproj | 35 +++++++++---------- csharp/app/SaliMax/src/AsciiArt.cs | 2 +- csharp/app/SaliMax/src/BusPort.cs | 2 +- .../src/Controller/AvgBatteriesStatus.cs | 2 +- csharp/app/SaliMax/src/Controller/Control.cs | 4 +-- .../SaliMax/src/Controller/ControlRecord.cs | 6 ++-- .../SaliMax/src/Controller/ControlTarget.cs | 2 +- .../app/SaliMax/src/Controller/Controller.cs | 10 +++--- .../SaliMax/src/Controller/SaliMaxState.cs | 2 +- csharp/app/SaliMax/src/Controller/State.cs | 2 +- .../app/SaliMax/src/Controller/StateConfig.cs | 2 +- .../SaliMax/src/Controller/StatusRecord.cs | 8 ++--- csharp/app/SaliMax/src/Log/Ampt.cs | 4 +-- csharp/app/SaliMax/src/Log/Battery48Tl.cs | 2 +- csharp/app/SaliMax/src/Log/EmuMeter.cs | 4 +-- csharp/app/SaliMax/src/Log/JsonUtil.cs | 2 +- csharp/app/SaliMax/src/Log/Salimax.cs | 6 ++-- csharp/app/SaliMax/src/Log/TruConvertAc.cs | 4 +-- csharp/app/SaliMax/src/Log/TruConvertDc.cs | 4 +-- csharp/app/SaliMax/src/Program.cs | 20 +++++------ csharp/app/SaliMax/src/S3Config.cs | 2 +- .../src/SaliMaxRelays/RelayMapBoolean.cs | 2 +- .../src/SaliMaxRelays/SaliMaxRelaysDevice.cs | 2 +- .../src/SaliMaxRelays/SaliMaxRelaysStatus.cs | 2 +- csharp/app/SaliMax/src/SystemConfig/Config.cs | 2 +- .../app/SaliMax/src/SystemConfig/Defaults.cs | 2 +- .../SaliMax/src/SystemConfig/SalimaxConfig.cs | 4 +-- csharp/app/SaliMax/src/Topology.cs | 8 ++--- csharp/app/SaliMax/src/Utils.cs | 2 +- csharp/lib/Channels/Channels.csproj | 4 --- .../Channels/V2/Bak/Connections/Connection.cs | 2 +- .../V2/Bak/Connections/Connections.cs | 2 +- .../Channels/V2/Bak/Connections/Extensions.cs | 2 +- .../V2/Bak/Connections/IConnection.cs | 2 +- csharp/lib/Channels/V2/Bak/GenericChannel.cs | 4 +-- csharp/lib/Devices/AMPT/Ampt.csproj | 2 +- .../lib/Devices/AMPT/AmptCommunicationUnit.cs | 2 +- csharp/lib/Devices/AMPT/AmptDeviceStatus.cs | 2 +- csharp/lib/Devices/AMPT/AmptStatus.cs | 5 +-- csharp/lib/Devices/AMPT/AmptStringStatus.cs | 2 +- csharp/lib/Devices/Adam6060/Adam6060.csproj | 2 +- .../Devices/Battery48TL/Battery48TL.csproj | 2 +- csharp/lib/Devices/EmuMeter/EmuMeter.csproj | 2 +- .../Trumpf/TruConvert/TruConvert.csproj | 8 ++--- .../Trumpf/TruConvertAc/AlarmMessage.cs | 2 +- .../Trumpf/TruConvertAc/TruConvertAc.csproj | 2 +- .../Trumpf/TruConvertAc/WarningMessage.cs | 2 +- .../Trumpf/TruConvertDc/TruConvertDc.csproj | 2 +- csharp/lib/InnovEnergy.lib.props | 1 + csharp/lib/Protocols/DBus/DBus.csproj | 2 +- csharp/lib/Protocols/Modbus/Modbus.csproj | 2 +- csharp/lib/S3/DataRec.cs | 4 +-- .../Drivers/Internal/Delegates/ReadRecord.cs | 6 ++-- .../Drivers/Internal/Delegates/WriteRecord.cs | 6 ++-- csharp/lib/S3/Drivers/Internal/Reader.cs | 10 +++--- .../lib/S3/Drivers/Internal/Reader.public.cs | 8 ++--- .../S3/Drivers/Internal/Util/Aggregator.cs | 8 ++--- .../lib/S3/Drivers/Internal/Util/Sampler.cs | 10 +++--- csharp/lib/S3/Drivers/Internal/Writer.cs | 14 ++++---- .../lib/S3/Drivers/Internal/Writer.public.cs | 8 ++--- csharp/lib/S3/Drivers/MemoryDriver.cs | 12 +++---- csharp/lib/S3/Drivers/S3Config.cs | 2 +- csharp/lib/S3/Drivers/S3Driver.cs | 16 ++++----- csharp/lib/S3/Metadata/AggregationLevel.cs | 4 +-- csharp/lib/S3/Metadata/FieldType.cs | 2 +- csharp/lib/S3/Program.cs | 10 +++--- csharp/lib/S3/Records/Fields/Field.cs | 2 +- csharp/lib/S3/Records/Fields/NumberField.cs | 2 +- csharp/lib/S3/Records/Fields/TextField.cs | 2 +- csharp/lib/S3/Records/Fields/TextFrequency.cs | 2 +- csharp/lib/S3/Records/Fields/UnitAttribute.cs | 2 +- csharp/lib/S3/Records/Fields/WithUnit.cs | 2 +- .../lib/S3/Records/Operations/Aggregation.cs | 6 ++-- .../lib/S3/Records/Operations/Conversion.cs | 4 +-- csharp/lib/S3/Records/Record.cs | 8 ++--- .../lib/S3/Records/Serialization/FieldTag.cs | 2 +- csharp/lib/S3/Records/Serialization/Parser.cs | 8 ++--- .../S3/Records/Serialization/Serializer.cs | 8 ++--- .../Records/Specialized/AggregatedRecord.cs | 6 ++-- .../Records/Specialized/TimeStampedRecord.cs | 4 +-- csharp/lib/S3/S3.csproj | 5 --- csharp/lib/StatusApi/StatusApi.csproj | 2 +- csharp/lib/{Units => StatusData}/Current.cs | 4 +-- .../{Units => StatusData}/Json/Converters.cs | 2 +- .../Json/CurrentConverter.cs | 2 +- .../Json/PowerConverter.cs | 2 +- .../Json/ResistanceConverter.cs | 2 +- .../Json/VoltageConverter.cs | 2 +- csharp/lib/{Units => StatusData}/Power.cs | 4 ++- .../lib/{Units => StatusData}/Resistance.cs | 2 +- csharp/lib/StatusData/State.cs | 21 +++++++++++ .../StatusData.csproj} | 2 +- csharp/lib/{Units => StatusData}/Units.cs | 2 +- csharp/lib/{Units => StatusData}/Voltage.cs | 2 +- .../SysTools/Edges/RemoteCommandToProcess.cs | 6 ++-- .../Edges/RemotePathToRemoteCommand.cs | 4 +-- .../SysTools/Edges/SshHostToRemoteCommand.cs | 4 +-- .../lib/SysTools/Edges/SshHostToRemotePath.cs | 4 +-- csharp/lib/SysTools/Edges/StringToCommand.cs | 2 +- csharp/lib/SysTools/Edges/StringToProcess.cs | 4 +-- .../lib/SysTools/Edges/StringToRemotePath.cs | 4 +-- csharp/lib/SysTools/Edges/StringToSysPath.cs | 2 +- .../lib/SysTools/Edges/SysCommandToProcess.cs | 4 +-- .../Edges/SysCommandToRemoteCommand.cs | 4 +-- csharp/lib/SysTools/Edges/SysPathToProcess.cs | 4 +-- .../lib/SysTools/Edges/SysPathToRemotePath.cs | 4 +-- .../lib/SysTools/Edges/SysPathToSysCommand.cs | 2 +- csharp/lib/SysTools/FileIo.cs | 4 +-- csharp/lib/SysTools/Process/AsyncProcess.cs | 4 +-- csharp/lib/SysTools/Process/ProcessResult.cs | 4 +-- csharp/lib/SysTools/Process/SyncProcess.cs | 4 +-- csharp/lib/SysTools/Remote/RemoteCommand.cs | 4 +-- csharp/lib/SysTools/Remote/RemoteFileIo.cs | 6 ++-- csharp/lib/SysTools/Remote/RemotePath.cs | 2 +- csharp/lib/SysTools/Remote/SshHost.cs | 6 ++-- csharp/lib/SysTools/SysCommand.cs | 4 +-- csharp/lib/SysTools/SysDirs.cs | 2 +- csharp/lib/SysTools/SysPath.cs | 6 ++-- csharp/lib/SysTools/SysTools.csproj | 12 ------- csharp/lib/SysTools/Utils/ConsoleUtils.cs | 2 +- csharp/lib/SysTools/Utils/EnumerableUtils.cs | 2 +- csharp/lib/SysTools/Utils/StringUtils.cs | 2 +- csharp/lib/SysTools/Utils/Utils.cs | 2 +- csharp/lib/Time/Time.csproj | 6 ---- csharp/lib/Time/Unix/UnixTime.Compare.cs | 2 +- csharp/lib/Time/Unix/UnixTime.Constructors.cs | 2 +- csharp/lib/Time/Unix/UnixTime.Converters.cs | 2 +- csharp/lib/Time/Unix/UnixTime.Operators.cs | 2 +- csharp/lib/Time/Unix/UnixTime.Overrides.cs | 2 +- csharp/lib/Time/Unix/UnixTime.cs | 2 +- csharp/lib/Time/Unix/UnixTimeDelta.Compare.cs | 2 +- .../Time/Unix/UnixTimeDelta.Constructors.cs | 2 +- .../lib/Time/Unix/UnixTimeDelta.Operators.cs | 2 +- .../lib/Time/Unix/UnixTimeDelta.Overrides.cs | 2 +- .../lib/Time/Unix/UnixTimeDeltaExtensions.cs | 2 +- csharp/lib/Time/Unix/UnixTimeSpan.cs | 2 +- csharp/lib/Utils/Utils.csproj | 2 +- csharp/lib/Victron/VeDBus/VeDBus.csproj | 2 +- csharp/lib/Victron/VictronVRM/Installation.cs | 2 +- .../lib/Victron/VictronVRM/VictronVRM.csproj | 2 +- csharp/lib/WebServer/WebServer.csproj | 2 +- 198 files changed, 372 insertions(+), 430 deletions(-) rename csharp/lib/{Units => StatusData}/Current.cs (97%) rename csharp/lib/{Units => StatusData}/Json/Converters.cs (90%) rename csharp/lib/{Units => StatusData}/Json/CurrentConverter.cs (91%) rename csharp/lib/{Units => StatusData}/Json/PowerConverter.cs (90%) rename csharp/lib/{Units => StatusData}/Json/ResistanceConverter.cs (91%) rename csharp/lib/{Units => StatusData}/Json/VoltageConverter.cs (91%) rename csharp/lib/{Units => StatusData}/Power.cs (95%) rename csharp/lib/{Units => StatusData}/Resistance.cs (97%) create mode 100644 csharp/lib/StatusData/State.cs rename csharp/lib/{Units/Units.csproj => StatusData/StatusData.csproj} (75%) rename csharp/lib/{Units => StatusData}/Units.cs (89%) rename csharp/lib/{Units => StatusData}/Voltage.cs (97%) diff --git a/csharp/InnovEnergy.props b/csharp/InnovEnergy.props index 57ac5931e..c6c92bd2a 100644 --- a/csharp/InnovEnergy.props +++ b/csharp/InnovEnergy.props @@ -3,13 +3,14 @@ InnovEnergy enable - default + preview true - InnovEnergy enable net6.0 true false + $(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("lib/", "Lib/").Replace("app/", "App/").Replace("src/", "").Replace("/",".")) + $(Company) Team diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 69f33a105..5002df0a2 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -65,7 +65,7 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "app/Backend/Backend.csproj", "{A56F58C2-B265-435B-A985-53B4D6F49B1A}" EndProject EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Units", "lib/Units/Units.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusData", "lib\StatusData\StatusData.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" EndProject Global diff --git a/csharp/app/Backend/Backend.csproj b/csharp/app/Backend/Backend.csproj index e6a136cb1..eebe0dae8 100644 --- a/csharp/app/Backend/Backend.csproj +++ b/csharp/app/Backend/Backend.csproj @@ -1,12 +1,5 @@ - - - net6.0 - enable - enable - preview - Innovenergy.Backend - + @@ -28,17 +21,10 @@ - - - ..\..\..\..\..\..\.nuget\packages\awssdk.core\3.7.8.10\lib\netcoreapp3.1\AWSSDK.Core.dll - - - ..\..\..\..\..\.nuget\packages\sqlite-net-pcl\1.8.116\lib\netstandard2.0\SQLite-net.dll - - + - + diff --git a/csharp/app/BmsTunnel/BatteryConnection.cs b/csharp/app/BmsTunnel/BatteryConnection.cs index 1dd0378a6..28dd3ee8a 100644 --- a/csharp/app/BmsTunnel/BatteryConnection.cs +++ b/csharp/app/BmsTunnel/BatteryConnection.cs @@ -1,9 +1,9 @@ using CliWrap; using CliWrap.Buffered; using InnovEnergy.Lib.Utils; -using static InnovEnergy.BmsTunnel.CliPrograms; +using static InnovEnergy.App.BmsTunnel.CliPrograms; -namespace InnovEnergy.BmsTunnel; +namespace InnovEnergy.App.BmsTunnel; using Nodes = IReadOnlyList; diff --git a/csharp/app/BmsTunnel/BmsTunnel.cs b/csharp/app/BmsTunnel/BmsTunnel.cs index 2af527047..85cefdf14 100644 --- a/csharp/app/BmsTunnel/BmsTunnel.cs +++ b/csharp/app/BmsTunnel/BmsTunnel.cs @@ -3,7 +3,7 @@ using System.Text; using CliWrap.Buffered; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.BmsTunnel; +namespace InnovEnergy.App.BmsTunnel; public class BmsTunnel : IDisposable diff --git a/csharp/app/BmsTunnel/BmsTunnel.csproj b/csharp/app/BmsTunnel/BmsTunnel.csproj index 6078a616a..9fe1fc75d 100644 --- a/csharp/app/BmsTunnel/BmsTunnel.csproj +++ b/csharp/app/BmsTunnel/BmsTunnel.csproj @@ -1,10 +1,6 @@ - - InnovEnergy.BmsTunnel - - diff --git a/csharp/app/BmsTunnel/CliPrograms.cs b/csharp/app/BmsTunnel/CliPrograms.cs index 98588b622..c27df92df 100644 --- a/csharp/app/BmsTunnel/CliPrograms.cs +++ b/csharp/app/BmsTunnel/CliPrograms.cs @@ -1,6 +1,6 @@ using CliWrap; -namespace InnovEnergy.BmsTunnel; +namespace InnovEnergy.App.BmsTunnel; public static class CliPrograms { diff --git a/csharp/app/BmsTunnel/Program.cs b/csharp/app/BmsTunnel/Program.cs index 5f2d42de7..c3ce8f71e 100644 --- a/csharp/app/BmsTunnel/Program.cs +++ b/csharp/app/BmsTunnel/Program.cs @@ -5,7 +5,7 @@ using InnovEnergy.Lib.Utils; using static System.String; -namespace InnovEnergy.BmsTunnel; +namespace InnovEnergy.App.BmsTunnel; public static class Program { diff --git a/csharp/app/Collector/Collector.csproj b/csharp/app/Collector/Collector.csproj index 9bbb60eb9..b2e28418b 100644 --- a/csharp/app/Collector/Collector.csproj +++ b/csharp/app/Collector/Collector.csproj @@ -1,9 +1,5 @@ - - - InnovEnergy.Collector - diff --git a/csharp/app/Collector/src/BatteryDataParser.cs b/csharp/app/Collector/src/BatteryDataParser.cs index 81c84313e..23e0c2bfb 100644 --- a/csharp/app/Collector/src/BatteryDataParser.cs +++ b/csharp/app/Collector/src/BatteryDataParser.cs @@ -1,14 +1,14 @@ using System.Net; using System.Text; -using InnovEnergy.Collector.Influx; -using InnovEnergy.Collector.Records; -using InnovEnergy.Collector.Utils; +using InnovEnergy.App.Collector.Influx; +using InnovEnergy.App.Collector.Records; +using InnovEnergy.App.Collector.Utils; using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils.Net; using Convert = System.Convert; -namespace InnovEnergy.Collector; +namespace InnovEnergy.App.Collector; using Data = IReadOnlyList; diff --git a/csharp/app/Collector/src/BatteryDataParserV4.cs b/csharp/app/Collector/src/BatteryDataParserV4.cs index dc3064f0c..8d8ae5bd0 100644 --- a/csharp/app/Collector/src/BatteryDataParserV4.cs +++ b/csharp/app/Collector/src/BatteryDataParserV4.cs @@ -1,15 +1,15 @@ using System.Net; using System.Text; -using InnovEnergy.Collector.Influx; -using InnovEnergy.Collector.Records; -using InnovEnergy.Collector.Utils; +using InnovEnergy.App.Collector.Influx; +using InnovEnergy.App.Collector.Records; +using InnovEnergy.App.Collector.Utils; using InnovEnergy.Lib.Utils; using Convert = System.Convert; // NOT (YET) USED -namespace InnovEnergy.Collector; +namespace InnovEnergy.App.Collector; using Data = IReadOnlyList; diff --git a/csharp/app/Collector/src/Influx/FieldAttribute.cs b/csharp/app/Collector/src/Influx/FieldAttribute.cs index 9f8438ac7..58dc3d0ba 100644 --- a/csharp/app/Collector/src/Influx/FieldAttribute.cs +++ b/csharp/app/Collector/src/Influx/FieldAttribute.cs @@ -2,7 +2,7 @@ using static System.AttributeTargets; #nullable disable -namespace InnovEnergy.Collector.Influx; +namespace InnovEnergy.App.Collector.Influx; [AttributeUsage(Property)] public class FieldAttribute : Attribute diff --git a/csharp/app/Collector/src/Influx/InfluxRecord.cs b/csharp/app/Collector/src/Influx/InfluxRecord.cs index 4043f0837..6406ea876 100644 --- a/csharp/app/Collector/src/Influx/InfluxRecord.cs +++ b/csharp/app/Collector/src/Influx/InfluxRecord.cs @@ -1,10 +1,10 @@ using System.Text; -using InnovEnergy.Collector.Utils; +using InnovEnergy.App.Collector.Utils; using InnovEnergy.Lib.Utils; using static System.Globalization.CultureInfo; -using static InnovEnergy.Collector.Influx.LineProtocolSyntax; +using static InnovEnergy.App.Collector.Influx.LineProtocolSyntax; -namespace InnovEnergy.Collector.Influx; +namespace InnovEnergy.App.Collector.Influx; public static class InfluxRecord { diff --git a/csharp/app/Collector/src/Influx/LineProtocolSyntax.cs b/csharp/app/Collector/src/Influx/LineProtocolSyntax.cs index 95b1a2bd6..2c55b3725 100644 --- a/csharp/app/Collector/src/Influx/LineProtocolSyntax.cs +++ b/csharp/app/Collector/src/Influx/LineProtocolSyntax.cs @@ -1,7 +1,7 @@ using System.Diagnostics.CodeAnalysis; using static System.Globalization.CultureInfo; -namespace InnovEnergy.Collector.Influx; +namespace InnovEnergy.App.Collector.Influx; internal static class LineProtocolSyntax { diff --git a/csharp/app/Collector/src/Influx/TagAttribute.cs b/csharp/app/Collector/src/Influx/TagAttribute.cs index 3db4ee3a1..db028d6a8 100644 --- a/csharp/app/Collector/src/Influx/TagAttribute.cs +++ b/csharp/app/Collector/src/Influx/TagAttribute.cs @@ -1,6 +1,6 @@ using static System.AttributeTargets; -namespace InnovEnergy.Collector.Influx; +namespace InnovEnergy.App.Collector.Influx; [AttributeUsage(Property)] public class TagAttribute : Attribute diff --git a/csharp/app/Collector/src/Program.cs b/csharp/app/Collector/src/Program.cs index 01d02ce43..28b58dbcf 100644 --- a/csharp/app/Collector/src/Program.cs +++ b/csharp/app/Collector/src/Program.cs @@ -2,17 +2,17 @@ using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Reactive.Subjects; -using InnovEnergy.Collector.Influx; -using InnovEnergy.Collector.Records; -using InnovEnergy.Lib.Utils; -using static System.Text.Encoding; -using static InnovEnergy.Lib.Utils.ExceptionHandling; using System.Text.Json; +using InnovEnergy.App.Collector.Influx; +using InnovEnergy.App.Collector.Records; +using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils.Net; using InnovEnergy.Lib.WebServer; +using static System.Text.Encoding; +using static InnovEnergy.Lib.Utils.ExceptionHandling; -namespace InnovEnergy.Collector; +namespace InnovEnergy.App.Collector; // TODO: net6 diff --git a/csharp/app/Collector/src/Records/Alarms.cs b/csharp/app/Collector/src/Records/Alarms.cs index 959855519..793680e82 100644 --- a/csharp/app/Collector/src/Records/Alarms.cs +++ b/csharp/app/Collector/src/Records/Alarms.cs @@ -1,10 +1,10 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; // ReSharper disable IdentifierTypo // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable InconsistentNaming -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; public class Alarms : BatteryRecord { diff --git a/csharp/app/Collector/src/Records/BatteryRecord.cs b/csharp/app/Collector/src/Records/BatteryRecord.cs index a244d1a77..49cfcc00c 100644 --- a/csharp/app/Collector/src/Records/BatteryRecord.cs +++ b/csharp/app/Collector/src/Records/BatteryRecord.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; public abstract class BatteryRecord {} \ No newline at end of file diff --git a/csharp/app/Collector/src/Records/BatteryStatus.cs b/csharp/app/Collector/src/Records/BatteryStatus.cs index 25f2a6ab3..2816b7545 100644 --- a/csharp/app/Collector/src/Records/BatteryStatus.cs +++ b/csharp/app/Collector/src/Records/BatteryStatus.cs @@ -1,9 +1,9 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable MemberCanBePrivate.Global -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; public class BatteryStatus : BatteryRecord { diff --git a/csharp/app/Collector/src/Records/Error.cs b/csharp/app/Collector/src/Records/Error.cs index 3d151af2e..9ffa399ef 100644 --- a/csharp/app/Collector/src/Records/Error.cs +++ b/csharp/app/Collector/src/Records/Error.cs @@ -1,8 +1,8 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; // ReSharper disable UnusedAutoPropertyAccessor.Global -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; public class Error : BatteryRecord { diff --git a/csharp/app/Collector/src/Records/InstallationStatus.cs b/csharp/app/Collector/src/Records/InstallationStatus.cs index 99937ddb7..a93a4374c 100644 --- a/csharp/app/Collector/src/Records/InstallationStatus.cs +++ b/csharp/app/Collector/src/Records/InstallationStatus.cs @@ -1,6 +1,6 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; public class InstallationStatus : BatteryRecord { diff --git a/csharp/app/Collector/src/Records/IoStatus.cs b/csharp/app/Collector/src/Records/IoStatus.cs index 4d0791219..a9c2c7247 100644 --- a/csharp/app/Collector/src/Records/IoStatus.cs +++ b/csharp/app/Collector/src/Records/IoStatus.cs @@ -1,8 +1,8 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; // ReSharper disable UnusedAutoPropertyAccessor.Global -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; public class IoStatus : BatteryRecord { diff --git a/csharp/app/Collector/src/Records/Leds.cs b/csharp/app/Collector/src/Records/Leds.cs index 39a7e97be..6dc3170cb 100644 --- a/csharp/app/Collector/src/Records/Leds.cs +++ b/csharp/app/Collector/src/Records/Leds.cs @@ -1,9 +1,9 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedMember.Global -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; public class Leds : BatteryRecord { diff --git a/csharp/app/Collector/src/Records/Temperatures.cs b/csharp/app/Collector/src/Records/Temperatures.cs index 6b621084d..34d53a92e 100644 --- a/csharp/app/Collector/src/Records/Temperatures.cs +++ b/csharp/app/Collector/src/Records/Temperatures.cs @@ -1,7 +1,6 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; - -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; #pragma warning disable CS8618 diff --git a/csharp/app/Collector/src/Records/Warnings.cs b/csharp/app/Collector/src/Records/Warnings.cs index c74aee213..3d5d2a176 100644 --- a/csharp/app/Collector/src/Records/Warnings.cs +++ b/csharp/app/Collector/src/Records/Warnings.cs @@ -1,7 +1,6 @@ -using InnovEnergy.Collector.Influx; +using InnovEnergy.App.Collector.Influx; - -namespace InnovEnergy.Collector.Records; +namespace InnovEnergy.App.Collector.Records; #pragma warning disable CS8618 diff --git a/csharp/app/Collector/src/Settings.cs b/csharp/app/Collector/src/Settings.cs index 10502f536..7708dc819 100644 --- a/csharp/app/Collector/src/Settings.cs +++ b/csharp/app/Collector/src/Settings.cs @@ -1,6 +1,6 @@ using System.Net; -namespace InnovEnergy.Collector; +namespace InnovEnergy.App.Collector; public static class Settings { diff --git a/csharp/app/Collector/src/Utils/Extensions.cs b/csharp/app/Collector/src/Utils/Extensions.cs index 3371ec718..9b79e4ab4 100644 --- a/csharp/app/Collector/src/Utils/Extensions.cs +++ b/csharp/app/Collector/src/Utils/Extensions.cs @@ -1,6 +1,6 @@ using System.Globalization; -namespace InnovEnergy.Collector.Utils; +namespace InnovEnergy.App.Collector.Utils; public static class Extensions { diff --git a/csharp/app/Collector/src/Utils/Log.cs b/csharp/app/Collector/src/Utils/Log.cs index 316f41af3..8e32f0174 100644 --- a/csharp/app/Collector/src/Utils/Log.cs +++ b/csharp/app/Collector/src/Utils/Log.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Collector.Utils; +namespace InnovEnergy.App.Collector.Utils; internal static class Log { diff --git a/csharp/app/Collector/src/Utils/Property.cs b/csharp/app/Collector/src/Utils/Property.cs index 89d0aa012..ccf4b45ac 100644 --- a/csharp/app/Collector/src/Utils/Property.cs +++ b/csharp/app/Collector/src/Utils/Property.cs @@ -1,7 +1,7 @@ using System.Reflection; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.Collector.Utils; +namespace InnovEnergy.App.Collector.Utils; public readonly struct Property { diff --git a/csharp/app/Collector/src/Utils/ReadOnlyListExtensions.cs b/csharp/app/Collector/src/Utils/ReadOnlyListExtensions.cs index ec53ff191..7c8d915b3 100644 --- a/csharp/app/Collector/src/Utils/ReadOnlyListExtensions.cs +++ b/csharp/app/Collector/src/Utils/ReadOnlyListExtensions.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Collector.Utils; +namespace InnovEnergy.App.Collector.Utils; public static class ReadOnlyListExtensions { diff --git a/csharp/app/Collector/src/Utils/Utils.cs b/csharp/app/Collector/src/Utils/Utils.cs index fd47cc583..51c9d3fbb 100644 --- a/csharp/app/Collector/src/Utils/Utils.cs +++ b/csharp/app/Collector/src/Utils/Utils.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Collector.Utils; +namespace InnovEnergy.App.Collector.Utils; public static class Utils { diff --git a/csharp/app/EmuMeterDriver/Config.cs b/csharp/app/EmuMeterDriver/Config.cs index e7bad3e06..ee0ad64db 100644 --- a/csharp/app/EmuMeterDriver/Config.cs +++ b/csharp/app/EmuMeterDriver/Config.cs @@ -1,7 +1,7 @@ using System.Reflection; using InnovEnergy.Lib.Victron.VeDBus; -namespace InnovEnergy.EmuMeter; +namespace InnovEnergy.App.EmuMeterDriver; public static class Config { diff --git a/csharp/app/EmuMeterDriver/EmuMeterDriver.cs b/csharp/app/EmuMeterDriver/EmuMeterDriver.cs index 6e923678a..9c57f2c7a 100644 --- a/csharp/app/EmuMeterDriver/EmuMeterDriver.cs +++ b/csharp/app/EmuMeterDriver/EmuMeterDriver.cs @@ -5,8 +5,7 @@ using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Victron.VeDBus; - -namespace InnovEnergy.EmuMeter; +namespace InnovEnergy.App.EmuMeterDriver; public static class EmuMeterDriver { diff --git a/csharp/app/EmuMeterDriver/EmuMeterDriver.csproj b/csharp/app/EmuMeterDriver/EmuMeterDriver.csproj index 9132521ae..ae7263dc2 100644 --- a/csharp/app/EmuMeterDriver/EmuMeterDriver.csproj +++ b/csharp/app/EmuMeterDriver/EmuMeterDriver.csproj @@ -1,10 +1,6 @@ - - InnovEnergy.EmuMeter - - diff --git a/csharp/app/EmuMeterDriver/Nic.cs b/csharp/app/EmuMeterDriver/Nic.cs index 9ddb9096e..0b81b0843 100644 --- a/csharp/app/EmuMeterDriver/Nic.cs +++ b/csharp/app/EmuMeterDriver/Nic.cs @@ -2,7 +2,7 @@ using System.Text.Json.Nodes; using CliWrap; using CliWrap.Buffered; -namespace InnovEnergy.EmuMeter; +namespace InnovEnergy.App.EmuMeterDriver; public readonly struct Nic { diff --git a/csharp/app/EmuMeterDriver/Program.cs b/csharp/app/EmuMeterDriver/Program.cs index 8a8c70561..6ad63d04d 100644 --- a/csharp/app/EmuMeterDriver/Program.cs +++ b/csharp/app/EmuMeterDriver/Program.cs @@ -1,4 +1,4 @@ -using InnovEnergy.EmuMeter; +using InnovEnergy.App.EmuMeterDriver; using InnovEnergy.Lib.Protocols.DBus; using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils.Net; diff --git a/csharp/app/EmuMeterDriver/Signal.cs b/csharp/app/EmuMeterDriver/Signal.cs index e606e2f53..ef375bb91 100644 --- a/csharp/app/EmuMeterDriver/Signal.cs +++ b/csharp/app/EmuMeterDriver/Signal.cs @@ -2,7 +2,7 @@ using InnovEnergy.Lib.Devices.EmuMeter; using InnovEnergy.Lib.Protocols.DBus.Protocol.DataTypes; using InnovEnergy.Lib.Victron.VeDBus; -namespace InnovEnergy.EmuMeter; +namespace InnovEnergy.App.EmuMeterDriver; public record Signal(Func Source, ObjectPath Path, String Format = "") { diff --git a/csharp/app/EmuMeterDriver/Utils.cs b/csharp/app/EmuMeterDriver/Utils.cs index cab67bd3c..65f02de6a 100644 --- a/csharp/app/EmuMeterDriver/Utils.cs +++ b/csharp/app/EmuMeterDriver/Utils.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.EmuMeter; +namespace InnovEnergy.App.EmuMeterDriver; public static class Utils { diff --git a/csharp/app/InnovEnergy.app.props b/csharp/app/InnovEnergy.app.props index beb4a7a4a..38d62f4dc 100644 --- a/csharp/app/InnovEnergy.app.props +++ b/csharp/app/InnovEnergy.app.props @@ -11,7 +11,6 @@ true true true - @@ -20,6 +19,7 @@ Exe + InnovEnergy.App.$(AssemblyName) diff --git a/csharp/app/OpenVpnCertificatesServer/Files.cs b/csharp/app/OpenVpnCertificatesServer/Files.cs index 35f78f44b..00fbf58d5 100644 --- a/csharp/app/OpenVpnCertificatesServer/Files.cs +++ b/csharp/app/OpenVpnCertificatesServer/Files.cs @@ -1,6 +1,4 @@ -namespace InnovEnergy.OpenVpnCertificatesServer; - -using System; +namespace InnovEnergy.App.OpenVpnCertificatesServer; public static class Files { diff --git a/csharp/app/OpenVpnCertificatesServer/Http.cs b/csharp/app/OpenVpnCertificatesServer/Http.cs index 3f72fb5da..5442047ae 100644 --- a/csharp/app/OpenVpnCertificatesServer/Http.cs +++ b/csharp/app/OpenVpnCertificatesServer/Http.cs @@ -1,9 +1,8 @@ -namespace InnovEnergy.OpenVpnCertificatesServer; - -using System; using System.Net; using Flurl; +namespace InnovEnergy.App.OpenVpnCertificatesServer; + public static class Http { // TODO: use worker thread diff --git a/csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj b/csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj index c2110f3cb..2773cd430 100644 --- a/csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj +++ b/csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj @@ -1,10 +1,6 @@ - - InnovEnergy.OpenVpnCertificatesServer - - diff --git a/csharp/app/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs b/csharp/app/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs index ec35a7836..b782c8165 100644 --- a/csharp/app/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs +++ b/csharp/app/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs @@ -7,7 +7,7 @@ using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; using Org.BouncyCastle.X509; -namespace InnovEnergy.OpenVpnCertificatesServer.PKI; +namespace InnovEnergy.App.OpenVpnCertificatesServer.PKI; public static class CertificateAuthority { diff --git a/csharp/app/OpenVpnCertificatesServer/PKI/Pem.cs b/csharp/app/OpenVpnCertificatesServer/PKI/Pem.cs index 3698135ee..8015c4e71 100644 --- a/csharp/app/OpenVpnCertificatesServer/PKI/Pem.cs +++ b/csharp/app/OpenVpnCertificatesServer/PKI/Pem.cs @@ -1,6 +1,6 @@ using Org.BouncyCastle.OpenSsl; -namespace InnovEnergy.OpenVpnCertificatesServer.PKI; +namespace InnovEnergy.App.OpenVpnCertificatesServer.PKI; public static class Pem { diff --git a/csharp/app/OpenVpnCertificatesServer/PKI/PwdFinder.cs b/csharp/app/OpenVpnCertificatesServer/PKI/PwdFinder.cs index 70d54fd51..3bbe9354a 100644 --- a/csharp/app/OpenVpnCertificatesServer/PKI/PwdFinder.cs +++ b/csharp/app/OpenVpnCertificatesServer/PKI/PwdFinder.cs @@ -1,6 +1,6 @@ using Org.BouncyCastle.OpenSsl; -namespace InnovEnergy.OpenVpnCertificatesServer.PKI; +namespace InnovEnergy.App.OpenVpnCertificatesServer.PKI; public class PwdFinder : IPasswordFinder { diff --git a/csharp/app/OpenVpnCertificatesServer/Program.cs b/csharp/app/OpenVpnCertificatesServer/Program.cs index 3d765b2cd..c9bff3a03 100644 --- a/csharp/app/OpenVpnCertificatesServer/Program.cs +++ b/csharp/app/OpenVpnCertificatesServer/Program.cs @@ -1,15 +1,14 @@ -using InnovEnergy.Lib.Utils; -using InnovEnergy.Lib.Victron.VictronVRM; -using InnovEnergy.OpenVpnCertificatesServer.PKI; -using System.Diagnostics; +using System.Diagnostics; using System.Text; using Flurl; using ICSharpCode.SharpZipLib.Tar; +using InnovEnergy.App.OpenVpnCertificatesServer.PKI; +using InnovEnergy.Lib.Utils; +using InnovEnergy.Lib.Victron.VictronVRM; using Org.BouncyCastle.Crypto; +using static InnovEnergy.App.OpenVpnCertificatesServer.PKI.CertificateAuthority; -using static InnovEnergy.OpenVpnCertificatesServer.PKI.CertificateAuthority; - -namespace InnovEnergy.OpenVpnCertificatesServer; +namespace InnovEnergy.App.OpenVpnCertificatesServer; // dotnet publish OpenVpnCertificatesServer.csproj -c Release -r linux-x64 -p:PublishSingleFile=true --self-contained true && scp bin/Release/net6.0/linux-x64/publish/OpenVpnCertificatesServer ig@salidomo.innovenergy.ch:~/get_cert/get_cert diff --git a/csharp/app/OpenVpnCertificatesServer/Utils.cs b/csharp/app/OpenVpnCertificatesServer/Utils.cs index 9ed8734f7..aea6faf59 100644 --- a/csharp/app/OpenVpnCertificatesServer/Utils.cs +++ b/csharp/app/OpenVpnCertificatesServer/Utils.cs @@ -1,9 +1,8 @@ -namespace InnovEnergy.OpenVpnCertificatesServer; - -using System; using System.Text; using ICSharpCode.SharpZipLib.Tar; +namespace InnovEnergy.App.OpenVpnCertificatesServer; + public static class Utils { public static void WriteFile(this TarOutputStream tar, String fileName, Byte[] contents, Boolean executable = false) diff --git a/csharp/app/RemoteSupportConsole/Login.cs b/csharp/app/RemoteSupportConsole/Login.cs index 901fd7175..7e3edbe35 100644 --- a/csharp/app/RemoteSupportConsole/Login.cs +++ b/csharp/app/RemoteSupportConsole/Login.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public static class Login { diff --git a/csharp/app/RemoteSupportConsole/ObservablePipeSource.cs b/csharp/app/RemoteSupportConsole/ObservablePipeSource.cs index 281ee75f4..a5e1af9d7 100644 --- a/csharp/app/RemoteSupportConsole/ObservablePipeSource.cs +++ b/csharp/app/RemoteSupportConsole/ObservablePipeSource.cs @@ -2,7 +2,7 @@ using System.Reactive.Linq; using System.Reactive.Threading.Tasks; using CliWrap; -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public static class ObservablePipeSource { diff --git a/csharp/app/RemoteSupportConsole/Program.cs b/csharp/app/RemoteSupportConsole/Program.cs index bd21d71d0..7ce5cbdcd 100644 --- a/csharp/app/RemoteSupportConsole/Program.cs +++ b/csharp/app/RemoteSupportConsole/Program.cs @@ -4,7 +4,7 @@ using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Victron.VictronVRM; using static System.Globalization.CompareOptions; -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; // dotnet publish -c release -r ubuntu-x64 // dotnet publish RemoteSupportConsole.csproj -c Release -r linux-x64 -p:PublishSingleFile=true --self-contained true diff --git a/csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj b/csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj index 3a4a4aaa3..cb8c7d1b8 100644 --- a/csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj +++ b/csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj @@ -1,10 +1,6 @@ - - InnovEnergy.RemoteSupportConsole - - diff --git a/csharp/app/RemoteSupportConsole/Ssh.cs b/csharp/app/RemoteSupportConsole/Ssh.cs index 55502ecb7..d9acc9662 100644 --- a/csharp/app/RemoteSupportConsole/Ssh.cs +++ b/csharp/app/RemoteSupportConsole/Ssh.cs @@ -1,7 +1,7 @@ using CliWrap; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public static class Ssh { diff --git a/csharp/app/RemoteSupportConsole/VpnConnection.cs b/csharp/app/RemoteSupportConsole/VpnConnection.cs index 29f52b40c..b2442eea1 100644 --- a/csharp/app/RemoteSupportConsole/VpnConnection.cs +++ b/csharp/app/RemoteSupportConsole/VpnConnection.cs @@ -2,7 +2,7 @@ using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Victron.VictronVRM; using static System.ConsoleColor; -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public static class VpnConnection { diff --git a/csharp/app/RemoteSupportConsole/VpnInfo.cs b/csharp/app/RemoteSupportConsole/VpnInfo.cs index d7f39fbbc..0137a3b50 100644 --- a/csharp/app/RemoteSupportConsole/VpnInfo.cs +++ b/csharp/app/RemoteSupportConsole/VpnInfo.cs @@ -2,7 +2,7 @@ using Flurl; using Flurl.Http; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public static class VpnInfo { diff --git a/csharp/app/RemoteSupportConsole/VrmConnection.cs b/csharp/app/RemoteSupportConsole/VrmConnection.cs index 52515a025..03dd1e252 100644 --- a/csharp/app/RemoteSupportConsole/VrmConnection.cs +++ b/csharp/app/RemoteSupportConsole/VrmConnection.cs @@ -7,7 +7,7 @@ using InnovEnergy.Lib.Victron.VictronVRM; using static System.ConsoleColor; using static System.StringSplitOptions; -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public static class VrmConnection { diff --git a/csharp/app/RemoteSupportConsole/VrmInfo.cs b/csharp/app/RemoteSupportConsole/VrmInfo.cs index 9b37d00fc..32568ae23 100644 --- a/csharp/app/RemoteSupportConsole/VrmInfo.cs +++ b/csharp/app/RemoteSupportConsole/VrmInfo.cs @@ -3,7 +3,7 @@ using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Victron.VictronVRM; using static System.ConsoleColor; -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public static class VrmInfo diff --git a/csharp/app/RemoteSupportConsole/VrmProxy.cs b/csharp/app/RemoteSupportConsole/VrmProxy.cs index cc00370c5..c629c5476 100644 --- a/csharp/app/RemoteSupportConsole/VrmProxy.cs +++ b/csharp/app/RemoteSupportConsole/VrmProxy.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.RemoteSupportConsole; +namespace InnovEnergy.App.RemoteSupportConsole; public readonly record struct VrmProxy(IDisposable Connection, String User, String Host, String Port) : IDisposable { diff --git a/csharp/app/SaliMax/SaliMax.csproj b/csharp/app/SaliMax/SaliMax.csproj index 0893e2a24..2c2d378bd 100644 --- a/csharp/app/SaliMax/SaliMax.csproj +++ b/csharp/app/SaliMax/SaliMax.csproj @@ -1,25 +1,24 @@ - - InnovEnergy.SaliMax - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/csharp/app/SaliMax/src/AsciiArt.cs b/csharp/app/SaliMax/src/AsciiArt.cs index c8ffc4596..7485a1363 100644 --- a/csharp/app/SaliMax/src/AsciiArt.cs +++ b/csharp/app/SaliMax/src/AsciiArt.cs @@ -1,6 +1,6 @@ using InnovEnergy.Lib.Utils; -namespace InnovEnergy.SaliMax; +namespace InnovEnergy.App.SaliMax; public static class AsciiArt { diff --git a/csharp/app/SaliMax/src/BusPort.cs b/csharp/app/SaliMax/src/BusPort.cs index 20fc1c9a6..e8cbd649b 100644 --- a/csharp/app/SaliMax/src/BusPort.cs +++ b/csharp/app/SaliMax/src/BusPort.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SaliMax; +namespace InnovEnergy.App.SaliMax; public enum BusPort { diff --git a/csharp/app/SaliMax/src/Controller/AvgBatteriesStatus.cs b/csharp/app/SaliMax/src/Controller/AvgBatteriesStatus.cs index 7b90a6640..b62316d85 100644 --- a/csharp/app/SaliMax/src/Controller/AvgBatteriesStatus.cs +++ b/csharp/app/SaliMax/src/Controller/AvgBatteriesStatus.cs @@ -1,6 +1,6 @@ using InnovEnergy.Lib.Devices.Battery48TL; -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public class AvgBatteriesStatus { diff --git a/csharp/app/SaliMax/src/Controller/Control.cs b/csharp/app/SaliMax/src/Controller/Control.cs index 144e2b166..08589edb5 100644 --- a/csharp/app/SaliMax/src/Controller/Control.cs +++ b/csharp/app/SaliMax/src/Controller/Control.cs @@ -1,6 +1,4 @@ -using static InnovEnergy.SaliMax.SystemConfig.SalimaxConfig; - -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public static class Control { diff --git a/csharp/app/SaliMax/src/Controller/ControlRecord.cs b/csharp/app/SaliMax/src/Controller/ControlRecord.cs index c00373efb..ce7e4fc8f 100644 --- a/csharp/app/SaliMax/src/Controller/ControlRecord.cs +++ b/csharp/app/SaliMax/src/Controller/ControlRecord.cs @@ -1,9 +1,9 @@ +using InnovEnergy.App.SaliMax.SaliMaxRelays; +using InnovEnergy.App.SaliMax.SystemConfig; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; -using InnovEnergy.SaliMax.SaliMaxRelays; -using InnovEnergy.SaliMax.SystemConfig; -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public class ControlRecord { diff --git a/csharp/app/SaliMax/src/Controller/ControlTarget.cs b/csharp/app/SaliMax/src/Controller/ControlTarget.cs index d08fa47ab..1e279f8d3 100644 --- a/csharp/app/SaliMax/src/Controller/ControlTarget.cs +++ b/csharp/app/SaliMax/src/Controller/ControlTarget.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public enum ControlTarget // TODO to delete { diff --git a/csharp/app/SaliMax/src/Controller/Controller.cs b/csharp/app/SaliMax/src/Controller/Controller.cs index e578c5b2d..cadb47477 100644 --- a/csharp/app/SaliMax/src/Controller/Controller.cs +++ b/csharp/app/SaliMax/src/Controller/Controller.cs @@ -1,14 +1,14 @@ +using InnovEnergy.App.SaliMax.SaliMaxRelays; +using InnovEnergy.App.SaliMax.SystemConfig; using InnovEnergy.Lib.Devices.Trumpf.TruConvert; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -using InnovEnergy.SaliMax.SaliMaxRelays; -using InnovEnergy.SaliMax.SystemConfig; -using InnovEnergy.Time.Unix; -using static InnovEnergy.SaliMax.SaliMaxRelays.RelayState; +using static InnovEnergy.App.SaliMax.SaliMaxRelays.RelayState; -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public static class Controller { diff --git a/csharp/app/SaliMax/src/Controller/SaliMaxState.cs b/csharp/app/SaliMax/src/Controller/SaliMaxState.cs index cd81b24b5..be7470fae 100644 --- a/csharp/app/SaliMax/src/Controller/SaliMaxState.cs +++ b/csharp/app/SaliMax/src/Controller/SaliMaxState.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public struct SaliMaxState { diff --git a/csharp/app/SaliMax/src/Controller/State.cs b/csharp/app/SaliMax/src/Controller/State.cs index a8ad8d11b..7634d1d66 100644 --- a/csharp/app/SaliMax/src/Controller/State.cs +++ b/csharp/app/SaliMax/src/Controller/State.cs @@ -1,5 +1,5 @@ -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public enum State : Int16 { diff --git a/csharp/app/SaliMax/src/Controller/StateConfig.cs b/csharp/app/SaliMax/src/Controller/StateConfig.cs index be40aafc0..ce356d311 100644 --- a/csharp/app/SaliMax/src/Controller/StateConfig.cs +++ b/csharp/app/SaliMax/src/Controller/StateConfig.cs @@ -1,5 +1,5 @@ -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public static class StateConfig { diff --git a/csharp/app/SaliMax/src/Controller/StatusRecord.cs b/csharp/app/SaliMax/src/Controller/StatusRecord.cs index 0969b841b..53de658b8 100644 --- a/csharp/app/SaliMax/src/Controller/StatusRecord.cs +++ b/csharp/app/SaliMax/src/Controller/StatusRecord.cs @@ -1,12 +1,12 @@ -using InnovEnergy.Lib.Devices.Ampt; +using InnovEnergy.App.SaliMax.SaliMaxRelays; +using InnovEnergy.App.SaliMax.SystemConfig; +using InnovEnergy.Lib.Devices.AMPT; using InnovEnergy.Lib.Devices.Battery48TL; using InnovEnergy.Lib.Devices.EmuMeter; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; -using InnovEnergy.SaliMax.SaliMaxRelays; -using InnovEnergy.SaliMax.SystemConfig; -namespace InnovEnergy.SaliMax.Controller; +namespace InnovEnergy.App.SaliMax.Controller; public record StatusRecord { diff --git a/csharp/app/SaliMax/src/Log/Ampt.cs b/csharp/app/SaliMax/src/Log/Ampt.cs index 1a63b9eab..efaa6e388 100644 --- a/csharp/app/SaliMax/src/Log/Ampt.cs +++ b/csharp/app/SaliMax/src/Log/Ampt.cs @@ -1,8 +1,8 @@ using System.Text.Json.Nodes; -using InnovEnergy.Lib.Devices.Ampt; +using InnovEnergy.Lib.Devices.AMPT; using InnovEnergy.Lib.StatusApi; -namespace InnovEnergy.SaliMax.Log; +namespace InnovEnergy.App.SaliMax.Log; public static class Ampt { diff --git a/csharp/app/SaliMax/src/Log/Battery48Tl.cs b/csharp/app/SaliMax/src/Log/Battery48Tl.cs index db755c78d..f2c85bcbf 100644 --- a/csharp/app/SaliMax/src/Log/Battery48Tl.cs +++ b/csharp/app/SaliMax/src/Log/Battery48Tl.cs @@ -2,7 +2,7 @@ using System.Text.Json.Nodes; using InnovEnergy.Lib.Devices.Battery48TL; using InnovEnergy.Lib.StatusApi; -namespace InnovEnergy.SaliMax.Log; +namespace InnovEnergy.App.SaliMax.Log; public static class Battery48Tl { diff --git a/csharp/app/SaliMax/src/Log/EmuMeter.cs b/csharp/app/SaliMax/src/Log/EmuMeter.cs index 8b61199cf..bb5dbbf29 100644 --- a/csharp/app/SaliMax/src/Log/EmuMeter.cs +++ b/csharp/app/SaliMax/src/Log/EmuMeter.cs @@ -3,9 +3,9 @@ using InnovEnergy.Lib.Devices.EmuMeter; using InnovEnergy.Lib.StatusApi; using InnovEnergy.Lib.Utils; using static DecimalMath.DecimalEx; -using static InnovEnergy.SaliMax.Log.JsonUtil; +using static InnovEnergy.App.SaliMax.Log.JsonUtil; -namespace InnovEnergy.SaliMax.Log; +namespace InnovEnergy.App.SaliMax.Log; public static class EmuMeter { diff --git a/csharp/app/SaliMax/src/Log/JsonUtil.cs b/csharp/app/SaliMax/src/Log/JsonUtil.cs index 3201cb9b5..e82f2af01 100644 --- a/csharp/app/SaliMax/src/Log/JsonUtil.cs +++ b/csharp/app/SaliMax/src/Log/JsonUtil.cs @@ -1,7 +1,7 @@ using System.Text.Json.Nodes; using InnovEnergy.Lib.StatusApi; -namespace InnovEnergy.SaliMax.Log; +namespace InnovEnergy.App.SaliMax.Log; public static class JsonUtil { diff --git a/csharp/app/SaliMax/src/Log/Salimax.cs b/csharp/app/SaliMax/src/Log/Salimax.cs index 76bd25648..09a7de12f 100644 --- a/csharp/app/SaliMax/src/Log/Salimax.cs +++ b/csharp/app/SaliMax/src/Log/Salimax.cs @@ -1,9 +1,9 @@ using System.Text.Json.Nodes; +using InnovEnergy.App.SaliMax.Controller; using InnovEnergy.Lib.StatusApi; -using InnovEnergy.SaliMax.Controller; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.SaliMax.Log; +namespace InnovEnergy.App.SaliMax.Log; public static class Salimax { diff --git a/csharp/app/SaliMax/src/Log/TruConvertAc.cs b/csharp/app/SaliMax/src/Log/TruConvertAc.cs index eeb56ea4c..af49cbc66 100644 --- a/csharp/app/SaliMax/src/Log/TruConvertAc.cs +++ b/csharp/app/SaliMax/src/Log/TruConvertAc.cs @@ -2,9 +2,9 @@ using System.Text.Json.Nodes; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Utils; using static DecimalMath.DecimalEx; -using static InnovEnergy.SaliMax.Log.JsonUtil; +using static InnovEnergy.App.SaliMax.Log.JsonUtil; -namespace InnovEnergy.SaliMax.Log; +namespace InnovEnergy.App.SaliMax.Log; public static class TruConvertAc { diff --git a/csharp/app/SaliMax/src/Log/TruConvertDc.cs b/csharp/app/SaliMax/src/Log/TruConvertDc.cs index 09e39d1f2..34c23942b 100644 --- a/csharp/app/SaliMax/src/Log/TruConvertDc.cs +++ b/csharp/app/SaliMax/src/Log/TruConvertDc.cs @@ -1,8 +1,8 @@ using System.Text.Json.Nodes; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; -using static InnovEnergy.SaliMax.Log.JsonUtil; +using static InnovEnergy.App.SaliMax.Log.JsonUtil; -namespace InnovEnergy.SaliMax.Log; +namespace InnovEnergy.App.SaliMax.Log; using JO = JsonObject; diff --git a/csharp/app/SaliMax/src/Program.cs b/csharp/app/SaliMax/src/Program.cs index 0734b5b6f..229e3f0b8 100644 --- a/csharp/app/SaliMax/src/Program.cs +++ b/csharp/app/SaliMax/src/Program.cs @@ -1,27 +1,23 @@ - - - using System.Diagnostics; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using Flurl.Http; +using InnovEnergy.App.SaliMax.Controller; +using InnovEnergy.App.SaliMax.Log; +using InnovEnergy.App.SaliMax.SaliMaxRelays; +using InnovEnergy.App.SaliMax.SystemConfig; +using InnovEnergy.Lib.Devices.AMPT; +using InnovEnergy.Lib.Devices.Battery48TL; using InnovEnergy.Lib.Devices.EmuMeter; using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; -using InnovEnergy.Lib.Devices.Ampt; -using InnovEnergy.Lib.Devices.Battery48TL; -using InnovEnergy.SaliMax.Controller; -using InnovEnergy.SaliMax.Log; -using InnovEnergy.SaliMax.SaliMaxRelays; -using InnovEnergy.SaliMax.SystemConfig; -using InnovEnergy.Time.Unix; - +using InnovEnergy.Lib.Time.Unix; #pragma warning disable IL2026 -namespace InnovEnergy.SaliMax; +namespace InnovEnergy.App.SaliMax; internal static class Program { diff --git a/csharp/app/SaliMax/src/S3Config.cs b/csharp/app/SaliMax/src/S3Config.cs index 92238fb96..2e04acd81 100644 --- a/csharp/app/SaliMax/src/S3Config.cs +++ b/csharp/app/SaliMax/src/S3Config.cs @@ -5,7 +5,7 @@ using InnovEnergy.Lib.Utils; using static System.Text.Encoding; using Convert = System.Convert; -namespace InnovEnergy.SaliMax; +namespace InnovEnergy.App.SaliMax; public record S3Config { diff --git a/csharp/app/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs b/csharp/app/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs index c1408c2ff..bafd76793 100644 --- a/csharp/app/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs +++ b/csharp/app/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SaliMax.SaliMaxRelays; +namespace InnovEnergy.App.SaliMax.SaliMaxRelays; public enum RelayState { diff --git a/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs b/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs index 5fb1b8a69..4b5db1e06 100644 --- a/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs +++ b/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs @@ -1,7 +1,7 @@ using InnovEnergy.Lib.Devices.Adam6060; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.SaliMax.SaliMaxRelays; +namespace InnovEnergy.App.SaliMax.SaliMaxRelays; public class SaliMaxRelaysDevice { diff --git a/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs b/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs index 64c08b992..915896d54 100644 --- a/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs +++ b/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SaliMax.SaliMaxRelays; +namespace InnovEnergy.App.SaliMax.SaliMaxRelays; public record SaliMaxRelayStatus { diff --git a/csharp/app/SaliMax/src/SystemConfig/Config.cs b/csharp/app/SaliMax/src/SystemConfig/Config.cs index c11f7d6f7..73e42897a 100644 --- a/csharp/app/SaliMax/src/SystemConfig/Config.cs +++ b/csharp/app/SaliMax/src/SystemConfig/Config.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SaliMax.SystemConfig; +namespace InnovEnergy.App.SaliMax.SystemConfig; public static class Config { diff --git a/csharp/app/SaliMax/src/SystemConfig/Defaults.cs b/csharp/app/SaliMax/src/SystemConfig/Defaults.cs index 6b11b6ad1..1fcb95d25 100644 --- a/csharp/app/SaliMax/src/SystemConfig/Defaults.cs +++ b/csharp/app/SaliMax/src/SystemConfig/Defaults.cs @@ -1,7 +1,7 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; -namespace InnovEnergy.SaliMax.SystemConfig; +namespace InnovEnergy.App.SaliMax.SystemConfig; public static class Defaults { diff --git a/csharp/app/SaliMax/src/SystemConfig/SalimaxConfig.cs b/csharp/app/SaliMax/src/SystemConfig/SalimaxConfig.cs index 79d01fdd5..2170783e3 100644 --- a/csharp/app/SaliMax/src/SystemConfig/SalimaxConfig.cs +++ b/csharp/app/SaliMax/src/SystemConfig/SalimaxConfig.cs @@ -1,9 +1,9 @@ using System.Text.Json; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -using InnovEnergy.Time.Unix; using static System.Text.Json.JsonSerializer; -namespace InnovEnergy.SaliMax.SystemConfig; +namespace InnovEnergy.App.SaliMax.SystemConfig; // shut up trim warnings #pragma warning disable IL2026 diff --git a/csharp/app/SaliMax/src/Topology.cs b/csharp/app/SaliMax/src/Topology.cs index ab8a26ee9..f9db2b68b 100644 --- a/csharp/app/SaliMax/src/Topology.cs +++ b/csharp/app/SaliMax/src/Topology.cs @@ -1,10 +1,10 @@ -#undef BatteriesAllowed +#undef BatteriesAllowed +using InnovEnergy.App.SaliMax.Controller; +using InnovEnergy.App.SaliMax.Log; using InnovEnergy.Lib.Utils; -using InnovEnergy.SaliMax.Controller; -using InnovEnergy.SaliMax.Log; -namespace InnovEnergy.SaliMax; +namespace InnovEnergy.App.SaliMax; public static class Topology { diff --git a/csharp/app/SaliMax/src/Utils.cs b/csharp/app/SaliMax/src/Utils.cs index 337502413..4104b5384 100644 --- a/csharp/app/SaliMax/src/Utils.cs +++ b/csharp/app/SaliMax/src/Utils.cs @@ -1,6 +1,6 @@ using InnovEnergy.Lib.Utils; -namespace InnovEnergy.SaliMax; +namespace InnovEnergy.App.SaliMax; public static class Utils { diff --git a/csharp/lib/Channels/Channels.csproj b/csharp/lib/Channels/Channels.csproj index ad3b1fed5..38b2fa318 100644 --- a/csharp/lib/Channels/Channels.csproj +++ b/csharp/lib/Channels/Channels.csproj @@ -2,10 +2,6 @@ - - InnovEnergy.Lib.Channels - - diff --git a/csharp/lib/Channels/V2/Bak/Connections/Connection.cs b/csharp/lib/Channels/V2/Bak/Connections/Connection.cs index 82d0b9f67..ecd18b168 100644 --- a/csharp/lib/Channels/V2/Bak/Connections/Connection.cs +++ b/csharp/lib/Channels/V2/Bak/Connections/Connection.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Lib.Channels.V2.Connections; +namespace InnovEnergy.Lib.Channels.V2.Bak.Connections; public abstract class Connection : IConnection where C : IDisposable { diff --git a/csharp/lib/Channels/V2/Bak/Connections/Connections.cs b/csharp/lib/Channels/V2/Bak/Connections/Connections.cs index 1af0c31a1..12e2f7207 100644 --- a/csharp/lib/Channels/V2/Bak/Connections/Connections.cs +++ b/csharp/lib/Channels/V2/Bak/Connections/Connections.cs @@ -1,6 +1,6 @@ using System.Net.Sockets; -namespace InnovEnergy.Lib.Channels.V2.Connections; +namespace InnovEnergy.Lib.Channels.V2.Bak.Connections; public class TcpClientConnection : Connection { diff --git a/csharp/lib/Channels/V2/Bak/Connections/Extensions.cs b/csharp/lib/Channels/V2/Bak/Connections/Extensions.cs index 1dd40eb78..d681564ce 100644 --- a/csharp/lib/Channels/V2/Bak/Connections/Extensions.cs +++ b/csharp/lib/Channels/V2/Bak/Connections/Extensions.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Lib.Channels.V2.Connections; +namespace InnovEnergy.Lib.Channels.V2.Bak.Connections; public static class Connection { diff --git a/csharp/lib/Channels/V2/Bak/Connections/IConnection.cs b/csharp/lib/Channels/V2/Bak/Connections/IConnection.cs index 8490accec..7463f3132 100644 --- a/csharp/lib/Channels/V2/Bak/Connections/IConnection.cs +++ b/csharp/lib/Channels/V2/Bak/Connections/IConnection.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Lib.Channels.V2.Connections; +namespace InnovEnergy.Lib.Channels.V2.Bak.Connections; public interface IConnection { diff --git a/csharp/lib/Channels/V2/Bak/GenericChannel.cs b/csharp/lib/Channels/V2/Bak/GenericChannel.cs index 6cad9ba22..151bc8aea 100644 --- a/csharp/lib/Channels/V2/Bak/GenericChannel.cs +++ b/csharp/lib/Channels/V2/Bak/GenericChannel.cs @@ -1,6 +1,6 @@ -using InnovEnergy.Lib.Channels.V2.Connections; +using InnovEnergy.Lib.Channels.V2.Bak.Connections; -namespace InnovEnergy.Lib.Channels.V2; +namespace InnovEnergy.Lib.Channels.V2.Bak; public abstract class GenericChannel2 : IChannel, IConnection { diff --git a/csharp/lib/Devices/AMPT/Ampt.csproj b/csharp/lib/Devices/AMPT/Ampt.csproj index 5f3e41475..a576a4ee7 100644 --- a/csharp/lib/Devices/AMPT/Ampt.csproj +++ b/csharp/lib/Devices/AMPT/Ampt.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.Devices.Ampt - InnovEnergy.Lib.Devices.Ampt + diff --git a/csharp/lib/Devices/AMPT/AmptCommunicationUnit.cs b/csharp/lib/Devices/AMPT/AmptCommunicationUnit.cs index 239502762..e701c8463 100644 --- a/csharp/lib/Devices/AMPT/AmptCommunicationUnit.cs +++ b/csharp/lib/Devices/AMPT/AmptCommunicationUnit.cs @@ -3,7 +3,7 @@ using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.StatusApi.Connections; -namespace InnovEnergy.Lib.Devices.Ampt; +namespace InnovEnergy.Lib.Devices.AMPT; public class AmptCommunicationUnit { diff --git a/csharp/lib/Devices/AMPT/AmptDeviceStatus.cs b/csharp/lib/Devices/AMPT/AmptDeviceStatus.cs index 00d9e352f..371395e46 100644 --- a/csharp/lib/Devices/AMPT/AmptDeviceStatus.cs +++ b/csharp/lib/Devices/AMPT/AmptDeviceStatus.cs @@ -1,7 +1,7 @@ using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Devices; -namespace InnovEnergy.Lib.Devices.Ampt; +namespace InnovEnergy.Lib.Devices.AMPT; public record AmptDeviceStatus ( diff --git a/csharp/lib/Devices/AMPT/AmptStatus.cs b/csharp/lib/Devices/AMPT/AmptStatus.cs index 48ce01d2f..45ff33662 100644 --- a/csharp/lib/Devices/AMPT/AmptStatus.cs +++ b/csharp/lib/Devices/AMPT/AmptStatus.cs @@ -1,7 +1,4 @@ -using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Devices; - -namespace InnovEnergy.Lib.Devices.Ampt; +namespace InnovEnergy.Lib.Devices.AMPT; public record AmptStatus ( diff --git a/csharp/lib/Devices/AMPT/AmptStringStatus.cs b/csharp/lib/Devices/AMPT/AmptStringStatus.cs index e8776950f..bd3b2c5e0 100644 --- a/csharp/lib/Devices/AMPT/AmptStringStatus.cs +++ b/csharp/lib/Devices/AMPT/AmptStringStatus.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Lib.Devices.Ampt; +namespace InnovEnergy.Lib.Devices.AMPT; public record AmptStringStatus { diff --git a/csharp/lib/Devices/Adam6060/Adam6060.csproj b/csharp/lib/Devices/Adam6060/Adam6060.csproj index f4fcbcbb6..9cc351396 100644 --- a/csharp/lib/Devices/Adam6060/Adam6060.csproj +++ b/csharp/lib/Devices/Adam6060/Adam6060.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.Devices.Adam6060 - InnovEnergy.Lib.Devices.Adam6060 + diff --git a/csharp/lib/Devices/Battery48TL/Battery48TL.csproj b/csharp/lib/Devices/Battery48TL/Battery48TL.csproj index 51feacfe1..5007b1d4b 100644 --- a/csharp/lib/Devices/Battery48TL/Battery48TL.csproj +++ b/csharp/lib/Devices/Battery48TL/Battery48TL.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.Devices.Battery48TL - InnovEnergy.Lib.Devices.Battery48TL + diff --git a/csharp/lib/Devices/EmuMeter/EmuMeter.csproj b/csharp/lib/Devices/EmuMeter/EmuMeter.csproj index c05adbe6b..fc57021a4 100644 --- a/csharp/lib/Devices/EmuMeter/EmuMeter.csproj +++ b/csharp/lib/Devices/EmuMeter/EmuMeter.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.Devices.EmuMeter - InnovEnergy.Lib.Devices.EmuMeter + diff --git a/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj b/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj index 0f5571422..ffe741177 100644 --- a/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj +++ b/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj @@ -2,14 +2,12 @@ - InnovEnergy.Lib.Devices.Trumpf.TruConvert - InnovEnergy.Lib.Devices.Trumpf.TruConvert - latest + - + - + diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs b/csharp/lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs index aceada544..df5535008 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs +++ b/csharp/lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs @@ -1,6 +1,6 @@ using System.Diagnostics.CodeAnalysis; -namespace InnovEnergy.Lib.Devices.Trumpf.TruConvert; +namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; [SuppressMessage("ReSharper", "IdentifierTypo")] [SuppressMessage("ReSharper", "UnusedMember.Global")] diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj b/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj index 31669d385..0e28aa423 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj +++ b/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.Devices.Trumpf.TruConvertAc - InnovEnergy.Lib.Devices.Trumpf.TruConvertAc + latest diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs b/csharp/lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs index 45a5538de..2fb74b947 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs +++ b/csharp/lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs @@ -1,6 +1,6 @@ using System.Diagnostics.CodeAnalysis; -namespace InnovEnergy.Lib.Devices.Trumpf.TruConvert; +namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; [SuppressMessage("ReSharper", "IdentifierTypo")] [SuppressMessage("ReSharper", "UnusedMember.Global")] diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj b/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj index c2acc0062..109275eee 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj +++ b/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.Devices.Trumpf.TruConvertDc - InnovEnergy.Lib.Devices.Trumpf.TruConvertDc + latest diff --git a/csharp/lib/InnovEnergy.lib.props b/csharp/lib/InnovEnergy.lib.props index 0e1ca7736..de75048b8 100644 --- a/csharp/lib/InnovEnergy.lib.props +++ b/csharp/lib/InnovEnergy.lib.props @@ -4,6 +4,7 @@ Library + $(RootNamespace) diff --git a/csharp/lib/Protocols/DBus/DBus.csproj b/csharp/lib/Protocols/DBus/DBus.csproj index 7f74a94ad..7a32ff8a1 100644 --- a/csharp/lib/Protocols/DBus/DBus.csproj +++ b/csharp/lib/Protocols/DBus/DBus.csproj @@ -5,7 +5,7 @@ DBus Library true InnovEnergy.Lib.Protocols.DBus - InnovEnergy.Lib.Protocols.DBus + diff --git a/csharp/lib/Protocols/Modbus/Modbus.csproj b/csharp/lib/Protocols/Modbus/Modbus.csproj index ec6eb7bf8..18f18b58f 100644 --- a/csharp/lib/Protocols/Modbus/Modbus.csproj +++ b/csharp/lib/Protocols/Modbus/Modbus.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.Protocols.Modbus - InnovEnergy.Lib.Protocols.Modbus + diff --git a/csharp/lib/S3/DataRec.cs b/csharp/lib/S3/DataRec.cs index f0d9b2e30..5ae585689 100644 --- a/csharp/lib/S3/DataRec.cs +++ b/csharp/lib/S3/DataRec.cs @@ -1,6 +1,6 @@ -using InnovEnergy.S3.Records.Fields; +using InnovEnergy.Lib.S3.Records.Fields; -namespace InnovEnergy.S3; +namespace InnovEnergy.Lib.S3; public record DataRec { diff --git a/csharp/lib/S3/Drivers/Internal/Delegates/ReadRecord.cs b/csharp/lib/S3/Drivers/Internal/Delegates/ReadRecord.cs index 82c56cda8..ad088d513 100644 --- a/csharp/lib/S3/Drivers/Internal/Delegates/ReadRecord.cs +++ b/csharp/lib/S3/Drivers/Internal/Delegates/ReadRecord.cs @@ -1,6 +1,6 @@ -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records.Specialized; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records.Specialized; -namespace InnovEnergy.S3.Drivers.Internal.Delegates; +namespace InnovEnergy.Lib.S3.Drivers.Internal.Delegates; public delegate Task ReadRecord(AggregationLevel level, UInt32 index); \ No newline at end of file diff --git a/csharp/lib/S3/Drivers/Internal/Delegates/WriteRecord.cs b/csharp/lib/S3/Drivers/Internal/Delegates/WriteRecord.cs index 3c06195ab..4bccde97d 100644 --- a/csharp/lib/S3/Drivers/Internal/Delegates/WriteRecord.cs +++ b/csharp/lib/S3/Drivers/Internal/Delegates/WriteRecord.cs @@ -1,6 +1,6 @@ -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records.Specialized; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records.Specialized; -namespace InnovEnergy.S3.Drivers.Internal.Delegates; +namespace InnovEnergy.Lib.S3.Drivers.Internal.Delegates; public delegate Task WriteRecord(TimeStampedRecord record, AggregationLevel level, UInt32 index); \ No newline at end of file diff --git a/csharp/lib/S3/Drivers/Internal/Reader.cs b/csharp/lib/S3/Drivers/Internal/Reader.cs index eccfc84c4..e5ba5c59e 100644 --- a/csharp/lib/S3/Drivers/Internal/Reader.cs +++ b/csharp/lib/S3/Drivers/Internal/Reader.cs @@ -1,10 +1,10 @@ -using InnovEnergy.S3.Drivers.Internal.Delegates; -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Drivers.Internal; +namespace InnovEnergy.Lib.S3.Drivers.Internal; public partial class Reader { diff --git a/csharp/lib/S3/Drivers/Internal/Reader.public.cs b/csharp/lib/S3/Drivers/Internal/Reader.public.cs index 622571c83..424b3ccfe 100644 --- a/csharp/lib/S3/Drivers/Internal/Reader.public.cs +++ b/csharp/lib/S3/Drivers/Internal/Reader.public.cs @@ -1,9 +1,9 @@ -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Drivers.Internal; +namespace InnovEnergy.Lib.S3.Drivers.Internal; public partial class Reader { diff --git a/csharp/lib/S3/Drivers/Internal/Util/Aggregator.cs b/csharp/lib/S3/Drivers/Internal/Util/Aggregator.cs index de1721858..999a2aa1a 100644 --- a/csharp/lib/S3/Drivers/Internal/Util/Aggregator.cs +++ b/csharp/lib/S3/Drivers/Internal/Util/Aggregator.cs @@ -1,9 +1,9 @@ -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records; -using InnovEnergy.S3.Records.Operations; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records; +using InnovEnergy.Lib.S3.Records.Operations; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Drivers.Internal.Util; +namespace InnovEnergy.Lib.S3.Drivers.Internal.Util; public class Aggregator { diff --git a/csharp/lib/S3/Drivers/Internal/Util/Sampler.cs b/csharp/lib/S3/Drivers/Internal/Util/Sampler.cs index e8b136265..384b00487 100644 --- a/csharp/lib/S3/Drivers/Internal/Util/Sampler.cs +++ b/csharp/lib/S3/Drivers/Internal/Util/Sampler.cs @@ -1,9 +1,9 @@ -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.S3.Drivers.Internal.Util; +namespace InnovEnergy.Lib.S3.Drivers.Internal.Util; internal class Sampler { diff --git a/csharp/lib/S3/Drivers/Internal/Writer.cs b/csharp/lib/S3/Drivers/Internal/Writer.cs index e9ee15700..19156a4d3 100644 --- a/csharp/lib/S3/Drivers/Internal/Writer.cs +++ b/csharp/lib/S3/Drivers/Internal/Writer.cs @@ -1,13 +1,13 @@ using System.Diagnostics; -using InnovEnergy.S3.Drivers.Internal.Delegates; -using InnovEnergy.S3.Drivers.Internal.Util; -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; +using InnovEnergy.Lib.S3.Drivers.Internal.Util; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Drivers.Internal; +namespace InnovEnergy.Lib.S3.Drivers.Internal; using AggregationLevels = IReadOnlyList; using Aggregators = IReadOnlyList; diff --git a/csharp/lib/S3/Drivers/Internal/Writer.public.cs b/csharp/lib/S3/Drivers/Internal/Writer.public.cs index 4d5ee131e..15ab491cf 100644 --- a/csharp/lib/S3/Drivers/Internal/Writer.public.cs +++ b/csharp/lib/S3/Drivers/Internal/Writer.public.cs @@ -1,9 +1,9 @@ -using InnovEnergy.S3.Records; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Records; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Drivers.Internal; +namespace InnovEnergy.Lib.S3.Drivers.Internal; public partial class Writer { diff --git a/csharp/lib/S3/Drivers/MemoryDriver.cs b/csharp/lib/S3/Drivers/MemoryDriver.cs index 31f3e998a..8b70abf5e 100644 --- a/csharp/lib/S3/Drivers/MemoryDriver.cs +++ b/csharp/lib/S3/Drivers/MemoryDriver.cs @@ -1,10 +1,10 @@ -using InnovEnergy.S3.Drivers.Internal; -using InnovEnergy.S3.Drivers.Internal.Delegates; -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Drivers.Internal; +using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.S3.Drivers; +namespace InnovEnergy.Lib.S3.Drivers; using Levels = IReadOnlyList; using Memory = Dictionary; diff --git a/csharp/lib/S3/Drivers/S3Config.cs b/csharp/lib/S3/Drivers/S3Config.cs index 4b4d60d18..758244b3f 100644 --- a/csharp/lib/S3/Drivers/S3Config.cs +++ b/csharp/lib/S3/Drivers/S3Config.cs @@ -5,7 +5,7 @@ using InnovEnergy.Lib.Utils; using static System.Text.Encoding; using Convert = System.Convert; -namespace InnovEnergy.S3.Drivers; +namespace InnovEnergy.Lib.S3.Drivers; public record S3Config { diff --git a/csharp/lib/S3/Drivers/S3Driver.cs b/csharp/lib/S3/Drivers/S3Driver.cs index 91a4ada47..9d231e998 100644 --- a/csharp/lib/S3/Drivers/S3Driver.cs +++ b/csharp/lib/S3/Drivers/S3Driver.cs @@ -1,16 +1,14 @@ using Flurl.Http; -using InnovEnergy.S3.Drivers.Internal; -using InnovEnergy.S3.Drivers.Internal.Delegates; -using InnovEnergy.S3.Metadata; -using InnovEnergy.S3.Records.Serialization; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Drivers.Internal; +using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.S3.Records.Serialization; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.S3.Drivers; +namespace InnovEnergy.Lib.S3.Drivers; using Levels = IReadOnlyList; -using Memory = Dictionary; - public class S3Driver : Writer { diff --git a/csharp/lib/S3/Metadata/AggregationLevel.cs b/csharp/lib/S3/Metadata/AggregationLevel.cs index 895ca3306..fd1ecd184 100644 --- a/csharp/lib/S3/Metadata/AggregationLevel.cs +++ b/csharp/lib/S3/Metadata/AggregationLevel.cs @@ -1,6 +1,6 @@ -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.S3.Metadata; +namespace InnovEnergy.Lib.S3.Metadata; public record AggregationLevel { diff --git a/csharp/lib/S3/Metadata/FieldType.cs b/csharp/lib/S3/Metadata/FieldType.cs index aa4093858..9ca91a1af 100644 --- a/csharp/lib/S3/Metadata/FieldType.cs +++ b/csharp/lib/S3/Metadata/FieldType.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.S3.Metadata; +namespace InnovEnergy.Lib.S3.Metadata; public enum FieldType { diff --git a/csharp/lib/S3/Program.cs b/csharp/lib/S3/Program.cs index 91fd538c8..4ba261f71 100644 --- a/csharp/lib/S3/Program.cs +++ b/csharp/lib/S3/Program.cs @@ -1,12 +1,14 @@ using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Reactive.Subjects; -using InnovEnergy.S3.Metadata; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -using static InnovEnergy.Time.Unix.UnixTimeSpan; +using static InnovEnergy.Lib.Time.Unix.UnixTimeSpan; + +namespace InnovEnergy.Lib.S3; + -namespace InnovEnergy.S3; public enum MyEnum { diff --git a/csharp/lib/S3/Records/Fields/Field.cs b/csharp/lib/S3/Records/Fields/Field.cs index 6831a6957..a68f29cd4 100644 --- a/csharp/lib/S3/Records/Fields/Field.cs +++ b/csharp/lib/S3/Records/Fields/Field.cs @@ -1,3 +1,3 @@ -namespace InnovEnergy.S3.Records.Fields; +namespace InnovEnergy.Lib.S3.Records.Fields; public abstract record Field; \ No newline at end of file diff --git a/csharp/lib/S3/Records/Fields/NumberField.cs b/csharp/lib/S3/Records/Fields/NumberField.cs index dca272106..62aca9f6c 100644 --- a/csharp/lib/S3/Records/Fields/NumberField.cs +++ b/csharp/lib/S3/Records/Fields/NumberField.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.S3.Records.Fields; +namespace InnovEnergy.Lib.S3.Records.Fields; public record NumberField : Field { diff --git a/csharp/lib/S3/Records/Fields/TextField.cs b/csharp/lib/S3/Records/Fields/TextField.cs index 561d50772..7b1ebd2e4 100644 --- a/csharp/lib/S3/Records/Fields/TextField.cs +++ b/csharp/lib/S3/Records/Fields/TextField.cs @@ -1,6 +1,6 @@ using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Records.Fields; +namespace InnovEnergy.Lib.S3.Records.Fields; public record TextField : Field { diff --git a/csharp/lib/S3/Records/Fields/TextFrequency.cs b/csharp/lib/S3/Records/Fields/TextFrequency.cs index 39631a4c1..60974957f 100644 --- a/csharp/lib/S3/Records/Fields/TextFrequency.cs +++ b/csharp/lib/S3/Records/Fields/TextFrequency.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.S3.Records.Fields; +namespace InnovEnergy.Lib.S3.Records.Fields; public record TextFrequency { diff --git a/csharp/lib/S3/Records/Fields/UnitAttribute.cs b/csharp/lib/S3/Records/Fields/UnitAttribute.cs index af47ca5b7..1bd25600c 100644 --- a/csharp/lib/S3/Records/Fields/UnitAttribute.cs +++ b/csharp/lib/S3/Records/Fields/UnitAttribute.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.S3.Records.Fields; +namespace InnovEnergy.Lib.S3.Records.Fields; [AttributeUsage(AttributeTargets.Property)] public sealed class UnitAttribute : Attribute diff --git a/csharp/lib/S3/Records/Fields/WithUnit.cs b/csharp/lib/S3/Records/Fields/WithUnit.cs index 26dcdc9ad..01104d9de 100644 --- a/csharp/lib/S3/Records/Fields/WithUnit.cs +++ b/csharp/lib/S3/Records/Fields/WithUnit.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.S3.Records.Fields; +namespace InnovEnergy.Lib.S3.Records.Fields; public readonly struct WithUnit { diff --git a/csharp/lib/S3/Records/Operations/Aggregation.cs b/csharp/lib/S3/Records/Operations/Aggregation.cs index b13ddd651..1b938947f 100644 --- a/csharp/lib/S3/Records/Operations/Aggregation.cs +++ b/csharp/lib/S3/Records/Operations/Aggregation.cs @@ -1,11 +1,11 @@ using System.Diagnostics.CodeAnalysis; -using InnovEnergy.S3.Records.Fields; +using InnovEnergy.Lib.S3.Records.Fields; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Records.Operations; +namespace InnovEnergy.Lib.S3.Records.Operations; // ReSharper disable ArgumentsStyleOther -using NamedField = KeyValuePair; + public static class Aggregation { diff --git a/csharp/lib/S3/Records/Operations/Conversion.cs b/csharp/lib/S3/Records/Operations/Conversion.cs index 489d9648f..cb68eb4ca 100644 --- a/csharp/lib/S3/Records/Operations/Conversion.cs +++ b/csharp/lib/S3/Records/Operations/Conversion.cs @@ -1,9 +1,9 @@ using System.Reflection; -using InnovEnergy.S3.Records.Fields; +using InnovEnergy.Lib.S3.Records.Fields; using InnovEnergy.Lib.Utils; using static System.Reflection.BindingFlags; -namespace InnovEnergy.S3.Records.Operations; +namespace InnovEnergy.Lib.S3.Records.Operations; public static class Conversion { diff --git a/csharp/lib/S3/Records/Record.cs b/csharp/lib/S3/Records/Record.cs index 050151c07..365765843 100644 --- a/csharp/lib/S3/Records/Record.cs +++ b/csharp/lib/S3/Records/Record.cs @@ -1,8 +1,8 @@ -using InnovEnergy.S3.Records.Fields; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Records.Fields; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.S3.Records; +namespace InnovEnergy.Lib.S3.Records; public record Record : Field { diff --git a/csharp/lib/S3/Records/Serialization/FieldTag.cs b/csharp/lib/S3/Records/Serialization/FieldTag.cs index 19d486da5..8dff3261b 100644 --- a/csharp/lib/S3/Records/Serialization/FieldTag.cs +++ b/csharp/lib/S3/Records/Serialization/FieldTag.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.S3.Records.Serialization; +namespace InnovEnergy.Lib.S3.Records.Serialization; public enum FieldTag : Byte { diff --git a/csharp/lib/S3/Records/Serialization/Parser.cs b/csharp/lib/S3/Records/Serialization/Parser.cs index 694b9bc26..76319a31a 100644 --- a/csharp/lib/S3/Records/Serialization/Parser.cs +++ b/csharp/lib/S3/Records/Serialization/Parser.cs @@ -1,10 +1,10 @@ using System.Text; -using InnovEnergy.S3.Records.Fields; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Records.Fields; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -namespace InnovEnergy.S3.Records.Serialization; +namespace InnovEnergy.Lib.S3.Records.Serialization; public class Parser { diff --git a/csharp/lib/S3/Records/Serialization/Serializer.cs b/csharp/lib/S3/Records/Serialization/Serializer.cs index 888132fbf..d7766df8d 100644 --- a/csharp/lib/S3/Records/Serialization/Serializer.cs +++ b/csharp/lib/S3/Records/Serialization/Serializer.cs @@ -1,10 +1,10 @@ -using InnovEnergy.S3.Records.Fields; -using InnovEnergy.S3.Records.Specialized; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Records.Fields; +using InnovEnergy.Lib.S3.Records.Specialized; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; using static System.Text.Encoding; -namespace InnovEnergy.S3.Records.Serialization; +namespace InnovEnergy.Lib.S3.Records.Serialization; public static class Serializer { diff --git a/csharp/lib/S3/Records/Specialized/AggregatedRecord.cs b/csharp/lib/S3/Records/Specialized/AggregatedRecord.cs index f8340d63d..e4b9a2283 100644 --- a/csharp/lib/S3/Records/Specialized/AggregatedRecord.cs +++ b/csharp/lib/S3/Records/Specialized/AggregatedRecord.cs @@ -1,7 +1,7 @@ -using InnovEnergy.S3.Metadata; -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.S3.Metadata; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.S3.Records.Specialized; +namespace InnovEnergy.Lib.S3.Records.Specialized; public readonly struct AggregatedRecord { diff --git a/csharp/lib/S3/Records/Specialized/TimeStampedRecord.cs b/csharp/lib/S3/Records/Specialized/TimeStampedRecord.cs index 28060830a..57dc56aed 100644 --- a/csharp/lib/S3/Records/Specialized/TimeStampedRecord.cs +++ b/csharp/lib/S3/Records/Specialized/TimeStampedRecord.cs @@ -1,6 +1,6 @@ -using InnovEnergy.Time.Unix; +using InnovEnergy.Lib.Time.Unix; -namespace InnovEnergy.S3.Records.Specialized; +namespace InnovEnergy.Lib.S3.Records.Specialized; public readonly struct TimeStampedRecord { diff --git a/csharp/lib/S3/S3.csproj b/csharp/lib/S3/S3.csproj index c68d60ec8..0da1127e5 100644 --- a/csharp/lib/S3/S3.csproj +++ b/csharp/lib/S3/S3.csproj @@ -2,11 +2,6 @@ - - InnovEnergy.S3 - latest - - diff --git a/csharp/lib/StatusApi/StatusApi.csproj b/csharp/lib/StatusApi/StatusApi.csproj index 96f7a934f..edc182ef8 100644 --- a/csharp/lib/StatusApi/StatusApi.csproj +++ b/csharp/lib/StatusApi/StatusApi.csproj @@ -3,7 +3,7 @@ InnovEnergy.Lib.StatusApi - InnovEnergy.Lib.StatusApi + diff --git a/csharp/lib/Units/Current.cs b/csharp/lib/StatusData/Current.cs similarity index 97% rename from csharp/lib/Units/Current.cs rename to csharp/lib/StatusData/Current.cs index e313271b8..2f65add3c 100644 --- a/csharp/lib/Units/Current.cs +++ b/csharp/lib/StatusData/Current.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Units; +namespace InnovEnergy.Lib.StatusData; public readonly struct Current { @@ -29,6 +29,4 @@ public readonly struct Current // U=RI public static Voltage operator *(Current current, Resistance resistance) => new Voltage(resistance.Value* current.Value); - - } \ No newline at end of file diff --git a/csharp/lib/Units/Json/Converters.cs b/csharp/lib/StatusData/Json/Converters.cs similarity index 90% rename from csharp/lib/Units/Json/Converters.cs rename to csharp/lib/StatusData/Json/Converters.cs index 81406754f..ab6a4336b 100644 --- a/csharp/lib/Units/Json/Converters.cs +++ b/csharp/lib/StatusData/Json/Converters.cs @@ -1,5 +1,5 @@ using System.Text.Json.Serialization; -using InnovEnergy.Units.Json; +using InnovEnergy.Lib.StatusData.Json; // ReSharper disable once CheckNamespace namespace InnovEnergy.Units; diff --git a/csharp/lib/Units/Json/CurrentConverter.cs b/csharp/lib/StatusData/Json/CurrentConverter.cs similarity index 91% rename from csharp/lib/Units/Json/CurrentConverter.cs rename to csharp/lib/StatusData/Json/CurrentConverter.cs index 93733110f..64707325f 100644 --- a/csharp/lib/Units/Json/CurrentConverter.cs +++ b/csharp/lib/StatusData/Json/CurrentConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Units.Json; +namespace InnovEnergy.Lib.StatusData.Json; public class CurrentConverter : JsonConverter { diff --git a/csharp/lib/Units/Json/PowerConverter.cs b/csharp/lib/StatusData/Json/PowerConverter.cs similarity index 90% rename from csharp/lib/Units/Json/PowerConverter.cs rename to csharp/lib/StatusData/Json/PowerConverter.cs index 037252da4..8c33d3eae 100644 --- a/csharp/lib/Units/Json/PowerConverter.cs +++ b/csharp/lib/StatusData/Json/PowerConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Units.Json; +namespace InnovEnergy.Lib.StatusData.Json; public class PowerConverter : JsonConverter { diff --git a/csharp/lib/Units/Json/ResistanceConverter.cs b/csharp/lib/StatusData/Json/ResistanceConverter.cs similarity index 91% rename from csharp/lib/Units/Json/ResistanceConverter.cs rename to csharp/lib/StatusData/Json/ResistanceConverter.cs index 022daff8c..a60d99009 100644 --- a/csharp/lib/Units/Json/ResistanceConverter.cs +++ b/csharp/lib/StatusData/Json/ResistanceConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Units.Json; +namespace InnovEnergy.Lib.StatusData.Json; public class ResistanceConverter : JsonConverter { diff --git a/csharp/lib/Units/Json/VoltageConverter.cs b/csharp/lib/StatusData/Json/VoltageConverter.cs similarity index 91% rename from csharp/lib/Units/Json/VoltageConverter.cs rename to csharp/lib/StatusData/Json/VoltageConverter.cs index 62922c1d7..b51ceabf5 100644 --- a/csharp/lib/Units/Json/VoltageConverter.cs +++ b/csharp/lib/StatusData/Json/VoltageConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Units.Json; +namespace InnovEnergy.Lib.StatusData.Json; public class VoltageConverter : JsonConverter { diff --git a/csharp/lib/Units/Power.cs b/csharp/lib/StatusData/Power.cs similarity index 95% rename from csharp/lib/Units/Power.cs rename to csharp/lib/StatusData/Power.cs index d6e88bccc..3a605dfca 100644 --- a/csharp/lib/Units/Power.cs +++ b/csharp/lib/StatusData/Power.cs @@ -1,4 +1,6 @@ -namespace InnovEnergy.Units; +using InnovEnergy.Units; + +namespace InnovEnergy.Lib.StatusData; public readonly struct Power { diff --git a/csharp/lib/Units/Resistance.cs b/csharp/lib/StatusData/Resistance.cs similarity index 97% rename from csharp/lib/Units/Resistance.cs rename to csharp/lib/StatusData/Resistance.cs index ae551e019..d10573e77 100644 --- a/csharp/lib/Units/Resistance.cs +++ b/csharp/lib/StatusData/Resistance.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Units; +namespace InnovEnergy.Lib.StatusData; public readonly struct Resistance { diff --git a/csharp/lib/StatusData/State.cs b/csharp/lib/StatusData/State.cs new file mode 100644 index 000000000..1f91b1249 --- /dev/null +++ b/csharp/lib/StatusData/State.cs @@ -0,0 +1,21 @@ +namespace InnovEnergy.Lib.StatusData; + +public readonly struct State +{ + public IReadOnlyList Values { get; } + + public State(IReadOnlyList values) => Values = values; + + public State(params String[] values) : this((IReadOnlyList)values){} + public State(params State[] states) : this(states.SelectMany(s => s.Values).ToList()){} + + public State(Enum e) : this(e.ToString()) + { + } + + public static implicit operator State(Enum e) => new State(e); + public static implicit operator State(String s) => new State(s); + + // parallel + public static State operator |(State left, State right) => new State(left, right); +} \ No newline at end of file diff --git a/csharp/lib/Units/Units.csproj b/csharp/lib/StatusData/StatusData.csproj similarity index 75% rename from csharp/lib/Units/Units.csproj rename to csharp/lib/StatusData/StatusData.csproj index 090825d42..22522002f 100644 --- a/csharp/lib/Units/Units.csproj +++ b/csharp/lib/StatusData/StatusData.csproj @@ -3,7 +3,7 @@ Library - InnovEnergy.Units + preview diff --git a/csharp/lib/Units/Units.cs b/csharp/lib/StatusData/Units.cs similarity index 89% rename from csharp/lib/Units/Units.cs rename to csharp/lib/StatusData/Units.cs index ced38eb03..4dacaa297 100644 --- a/csharp/lib/Units/Units.cs +++ b/csharp/lib/StatusData/Units.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Units; +namespace InnovEnergy.Lib.StatusData; public static partial class Units { diff --git a/csharp/lib/Units/Voltage.cs b/csharp/lib/StatusData/Voltage.cs similarity index 97% rename from csharp/lib/Units/Voltage.cs rename to csharp/lib/StatusData/Voltage.cs index ae39f9a0d..fa7c8a7fc 100644 --- a/csharp/lib/Units/Voltage.cs +++ b/csharp/lib/StatusData/Voltage.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Units; +namespace InnovEnergy.Lib.StatusData; public readonly struct Voltage { diff --git a/csharp/lib/SysTools/Edges/RemoteCommandToProcess.cs b/csharp/lib/SysTools/Edges/RemoteCommandToProcess.cs index 71453ab3d..984594e11 100644 --- a/csharp/lib/SysTools/Edges/RemoteCommandToProcess.cs +++ b/csharp/lib/SysTools/Edges/RemoteCommandToProcess.cs @@ -1,7 +1,7 @@ -using InnovEnergy.SysTools.Process; -using InnovEnergy.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Process; +using InnovEnergy.Lib.SysTools.Remote; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class RemoteCommandToProcess { diff --git a/csharp/lib/SysTools/Edges/RemotePathToRemoteCommand.cs b/csharp/lib/SysTools/Edges/RemotePathToRemoteCommand.cs index 112623032..5e882d473 100644 --- a/csharp/lib/SysTools/Edges/RemotePathToRemoteCommand.cs +++ b/csharp/lib/SysTools/Edges/RemotePathToRemoteCommand.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Remote; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class RemotePathToRemoteCommand { diff --git a/csharp/lib/SysTools/Edges/SshHostToRemoteCommand.cs b/csharp/lib/SysTools/Edges/SshHostToRemoteCommand.cs index 9dd56a042..c9cfba220 100644 --- a/csharp/lib/SysTools/Edges/SshHostToRemoteCommand.cs +++ b/csharp/lib/SysTools/Edges/SshHostToRemoteCommand.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Remote; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class SshHostToRemoteCommand { diff --git a/csharp/lib/SysTools/Edges/SshHostToRemotePath.cs b/csharp/lib/SysTools/Edges/SshHostToRemotePath.cs index 3d7c75156..4833861b6 100644 --- a/csharp/lib/SysTools/Edges/SshHostToRemotePath.cs +++ b/csharp/lib/SysTools/Edges/SshHostToRemotePath.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Remote; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class SshHostToRemotePath { diff --git a/csharp/lib/SysTools/Edges/StringToCommand.cs b/csharp/lib/SysTools/Edges/StringToCommand.cs index f905db3d8..1dc691b7f 100644 --- a/csharp/lib/SysTools/Edges/StringToCommand.cs +++ b/csharp/lib/SysTools/Edges/StringToCommand.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class StringToCommand { diff --git a/csharp/lib/SysTools/Edges/StringToProcess.cs b/csharp/lib/SysTools/Edges/StringToProcess.cs index 6a4229ef6..e8d3c4d63 100644 --- a/csharp/lib/SysTools/Edges/StringToProcess.cs +++ b/csharp/lib/SysTools/Edges/StringToProcess.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Process; +using InnovEnergy.Lib.SysTools.Process; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; using Env = Dictionary; diff --git a/csharp/lib/SysTools/Edges/StringToRemotePath.cs b/csharp/lib/SysTools/Edges/StringToRemotePath.cs index 5fd37b695..9a32e16b1 100644 --- a/csharp/lib/SysTools/Edges/StringToRemotePath.cs +++ b/csharp/lib/SysTools/Edges/StringToRemotePath.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Remote; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class StringToRemotePath { diff --git a/csharp/lib/SysTools/Edges/StringToSysPath.cs b/csharp/lib/SysTools/Edges/StringToSysPath.cs index 4e31e2836..bf7a93615 100644 --- a/csharp/lib/SysTools/Edges/StringToSysPath.cs +++ b/csharp/lib/SysTools/Edges/StringToSysPath.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class StringToSysPath { diff --git a/csharp/lib/SysTools/Edges/SysCommandToProcess.cs b/csharp/lib/SysTools/Edges/SysCommandToProcess.cs index ceee12ebe..b8b142b6f 100644 --- a/csharp/lib/SysTools/Edges/SysCommandToProcess.cs +++ b/csharp/lib/SysTools/Edges/SysCommandToProcess.cs @@ -1,9 +1,9 @@ using System.Diagnostics; using System.Reactive.Linq; using System.Text; -using InnovEnergy.SysTools.Process; +using InnovEnergy.Lib.SysTools.Process; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class SysCommandToProcess { diff --git a/csharp/lib/SysTools/Edges/SysCommandToRemoteCommand.cs b/csharp/lib/SysTools/Edges/SysCommandToRemoteCommand.cs index acb42b570..faa77d432 100644 --- a/csharp/lib/SysTools/Edges/SysCommandToRemoteCommand.cs +++ b/csharp/lib/SysTools/Edges/SysCommandToRemoteCommand.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Remote; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class SysCommandToRemoteCommand { diff --git a/csharp/lib/SysTools/Edges/SysPathToProcess.cs b/csharp/lib/SysTools/Edges/SysPathToProcess.cs index be8fe9904..60a030fe8 100644 --- a/csharp/lib/SysTools/Edges/SysPathToProcess.cs +++ b/csharp/lib/SysTools/Edges/SysPathToProcess.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Process; +using InnovEnergy.Lib.SysTools.Process; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class SysPathToProcess { diff --git a/csharp/lib/SysTools/Edges/SysPathToRemotePath.cs b/csharp/lib/SysTools/Edges/SysPathToRemotePath.cs index aebf6eade..410f6bb7e 100644 --- a/csharp/lib/SysTools/Edges/SysPathToRemotePath.cs +++ b/csharp/lib/SysTools/Edges/SysPathToRemotePath.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Remote; -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class SysPathToRemotePath { diff --git a/csharp/lib/SysTools/Edges/SysPathToSysCommand.cs b/csharp/lib/SysTools/Edges/SysPathToSysCommand.cs index 647778e9d..9f27e68ff 100644 --- a/csharp/lib/SysTools/Edges/SysPathToSysCommand.cs +++ b/csharp/lib/SysTools/Edges/SysPathToSysCommand.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Edges; +namespace InnovEnergy.Lib.SysTools.Edges; public static class SysPathToSysCommand { diff --git a/csharp/lib/SysTools/FileIo.cs b/csharp/lib/SysTools/FileIo.cs index 1df5a0adf..7328bd324 100644 --- a/csharp/lib/SysTools/FileIo.cs +++ b/csharp/lib/SysTools/FileIo.cs @@ -1,7 +1,7 @@ using System.Text; -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Utils; -namespace InnovEnergy.SysTools; +namespace InnovEnergy.Lib.SysTools; public static class FileIo { diff --git a/csharp/lib/SysTools/Process/AsyncProcess.cs b/csharp/lib/SysTools/Process/AsyncProcess.cs index c8c0f3262..3fb9e967f 100644 --- a/csharp/lib/SysTools/Process/AsyncProcess.cs +++ b/csharp/lib/SysTools/Process/AsyncProcess.cs @@ -2,10 +2,10 @@ using System.Diagnostics; using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Reactive.Subjects; -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Utils; using static System.ConsoleColor; -namespace InnovEnergy.SysTools.Process; +namespace InnovEnergy.Lib.SysTools.Process; using Env = Dictionary; diff --git a/csharp/lib/SysTools/Process/ProcessResult.cs b/csharp/lib/SysTools/Process/ProcessResult.cs index bf9f3a52a..162a2280d 100644 --- a/csharp/lib/SysTools/Process/ProcessResult.cs +++ b/csharp/lib/SysTools/Process/ProcessResult.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Utils; -namespace InnovEnergy.SysTools.Process; +namespace InnovEnergy.Lib.SysTools.Process; public readonly struct ProcessResult { diff --git a/csharp/lib/SysTools/Process/SyncProcess.cs b/csharp/lib/SysTools/Process/SyncProcess.cs index 89b23073e..36caedf3a 100644 --- a/csharp/lib/SysTools/Process/SyncProcess.cs +++ b/csharp/lib/SysTools/Process/SyncProcess.cs @@ -1,9 +1,9 @@ using System.Diagnostics; using System.Text.RegularExpressions; -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Utils; using static System.ConsoleColor; -namespace InnovEnergy.SysTools.Process; +namespace InnovEnergy.Lib.SysTools.Process; using Env = Dictionary; diff --git a/csharp/lib/SysTools/Remote/RemoteCommand.cs b/csharp/lib/SysTools/Remote/RemoteCommand.cs index 75d1febf5..69e59d571 100644 --- a/csharp/lib/SysTools/Remote/RemoteCommand.cs +++ b/csharp/lib/SysTools/Remote/RemoteCommand.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Utils; -namespace InnovEnergy.SysTools.Remote; +namespace InnovEnergy.Lib.SysTools.Remote; public readonly struct RemoteCommand { diff --git a/csharp/lib/SysTools/Remote/RemoteFileIo.cs b/csharp/lib/SysTools/Remote/RemoteFileIo.cs index 1ecdf6868..1444b5539 100644 --- a/csharp/lib/SysTools/Remote/RemoteFileIo.cs +++ b/csharp/lib/SysTools/Remote/RemoteFileIo.cs @@ -1,7 +1,7 @@ -using InnovEnergy.SysTools.Edges; -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Edges; +using InnovEnergy.Lib.SysTools.Utils; -namespace InnovEnergy.SysTools.Remote; +namespace InnovEnergy.Lib.SysTools.Remote; public static class RemoteFileIo { diff --git a/csharp/lib/SysTools/Remote/RemotePath.cs b/csharp/lib/SysTools/Remote/RemotePath.cs index e8a048bdd..97b21da39 100644 --- a/csharp/lib/SysTools/Remote/RemotePath.cs +++ b/csharp/lib/SysTools/Remote/RemotePath.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Remote; +namespace InnovEnergy.Lib.SysTools.Remote; public readonly struct RemotePath { diff --git a/csharp/lib/SysTools/Remote/SshHost.cs b/csharp/lib/SysTools/Remote/SshHost.cs index 7f7187302..5afade016 100644 --- a/csharp/lib/SysTools/Remote/SshHost.cs +++ b/csharp/lib/SysTools/Remote/SshHost.cs @@ -1,7 +1,7 @@ -using InnovEnergy.SysTools.Edges; -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Edges; +using InnovEnergy.Lib.SysTools.Utils; -namespace InnovEnergy.SysTools.Remote; +namespace InnovEnergy.Lib.SysTools.Remote; public readonly struct SshHost { diff --git a/csharp/lib/SysTools/SysCommand.cs b/csharp/lib/SysTools/SysCommand.cs index da3826e83..9d264c27d 100644 --- a/csharp/lib/SysTools/SysCommand.cs +++ b/csharp/lib/SysTools/SysCommand.cs @@ -1,6 +1,6 @@ -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Utils; -namespace InnovEnergy.SysTools; +namespace InnovEnergy.Lib.SysTools; public readonly struct SysCommand { diff --git a/csharp/lib/SysTools/SysDirs.cs b/csharp/lib/SysTools/SysDirs.cs index afec2e014..5c3c5bc68 100644 --- a/csharp/lib/SysTools/SysDirs.cs +++ b/csharp/lib/SysTools/SysDirs.cs @@ -1,7 +1,7 @@ using static System.Environment; using static System.Environment.SpecialFolder; -namespace InnovEnergy.SysTools; +namespace InnovEnergy.Lib.SysTools; public static class SysDirs { diff --git a/csharp/lib/SysTools/SysPath.cs b/csharp/lib/SysTools/SysPath.cs index 42bd090e0..383460ab8 100644 --- a/csharp/lib/SysTools/SysPath.cs +++ b/csharp/lib/SysTools/SysPath.cs @@ -1,9 +1,9 @@ using System.Text; -using InnovEnergy.SysTools.Remote; -using InnovEnergy.SysTools.Utils; +using InnovEnergy.Lib.SysTools.Remote; +using InnovEnergy.Lib.SysTools.Utils; using static System.IO.Path; -namespace InnovEnergy.SysTools; +namespace InnovEnergy.Lib.SysTools; public readonly struct SysPath { diff --git a/csharp/lib/SysTools/SysTools.csproj b/csharp/lib/SysTools/SysTools.csproj index 506350df6..aa11972a1 100644 --- a/csharp/lib/SysTools/SysTools.csproj +++ b/csharp/lib/SysTools/SysTools.csproj @@ -1,18 +1,6 @@ - - Library - - - - full - - - - InnovEnergy.SysTools - - diff --git a/csharp/lib/SysTools/Utils/ConsoleUtils.cs b/csharp/lib/SysTools/Utils/ConsoleUtils.cs index f1d418b3b..5c58ef3b4 100644 --- a/csharp/lib/SysTools/Utils/ConsoleUtils.cs +++ b/csharp/lib/SysTools/Utils/ConsoleUtils.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Utils; +namespace InnovEnergy.Lib.SysTools.Utils; internal static class ConsoleUtils { diff --git a/csharp/lib/SysTools/Utils/EnumerableUtils.cs b/csharp/lib/SysTools/Utils/EnumerableUtils.cs index e0e6338dc..16d6c8671 100644 --- a/csharp/lib/SysTools/Utils/EnumerableUtils.cs +++ b/csharp/lib/SysTools/Utils/EnumerableUtils.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Utils; +namespace InnovEnergy.Lib.SysTools.Utils; internal static class EnumerableUtils { diff --git a/csharp/lib/SysTools/Utils/StringUtils.cs b/csharp/lib/SysTools/Utils/StringUtils.cs index c67f724c7..c6a6ef12c 100644 --- a/csharp/lib/SysTools/Utils/StringUtils.cs +++ b/csharp/lib/SysTools/Utils/StringUtils.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Utils; +namespace InnovEnergy.Lib.SysTools.Utils; internal static class StringUtils { diff --git a/csharp/lib/SysTools/Utils/Utils.cs b/csharp/lib/SysTools/Utils/Utils.cs index 6129cc8df..73e37198e 100644 --- a/csharp/lib/SysTools/Utils/Utils.cs +++ b/csharp/lib/SysTools/Utils/Utils.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.SysTools.Utils; +namespace InnovEnergy.Lib.SysTools.Utils; public static class Utils { diff --git a/csharp/lib/Time/Time.csproj b/csharp/lib/Time/Time.csproj index 5b0b36b7e..a2a63460f 100644 --- a/csharp/lib/Time/Time.csproj +++ b/csharp/lib/Time/Time.csproj @@ -1,9 +1,3 @@ - - - Library - InnovEnergy.Time - - diff --git a/csharp/lib/Time/Unix/UnixTime.Compare.cs b/csharp/lib/Time/Unix/UnixTime.Compare.cs index ca91d5ce2..044ef1a32 100644 --- a/csharp/lib/Time/Unix/UnixTime.Compare.cs +++ b/csharp/lib/Time/Unix/UnixTime.Compare.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTime : IComparable, IEquatable { diff --git a/csharp/lib/Time/Unix/UnixTime.Constructors.cs b/csharp/lib/Time/Unix/UnixTime.Constructors.cs index ba26db8f3..5d963e488 100644 --- a/csharp/lib/Time/Unix/UnixTime.Constructors.cs +++ b/csharp/lib/Time/Unix/UnixTime.Constructors.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTime { diff --git a/csharp/lib/Time/Unix/UnixTime.Converters.cs b/csharp/lib/Time/Unix/UnixTime.Converters.cs index d8495f092..0d5d17aeb 100644 --- a/csharp/lib/Time/Unix/UnixTime.Converters.cs +++ b/csharp/lib/Time/Unix/UnixTime.Converters.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTime { diff --git a/csharp/lib/Time/Unix/UnixTime.Operators.cs b/csharp/lib/Time/Unix/UnixTime.Operators.cs index 850ccbfe3..7aeb71b69 100644 --- a/csharp/lib/Time/Unix/UnixTime.Operators.cs +++ b/csharp/lib/Time/Unix/UnixTime.Operators.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTime { diff --git a/csharp/lib/Time/Unix/UnixTime.Overrides.cs b/csharp/lib/Time/Unix/UnixTime.Overrides.cs index 66621de8e..c2ba77a5e 100644 --- a/csharp/lib/Time/Unix/UnixTime.Overrides.cs +++ b/csharp/lib/Time/Unix/UnixTime.Overrides.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTime { diff --git a/csharp/lib/Time/Unix/UnixTime.cs b/csharp/lib/Time/Unix/UnixTime.cs index b441c0c5f..f771fd01d 100644 --- a/csharp/lib/Time/Unix/UnixTime.cs +++ b/csharp/lib/Time/Unix/UnixTime.cs @@ -2,7 +2,7 @@ // ReSharper disable ArrangeStaticMemberQualifier -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTime { diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Compare.cs b/csharp/lib/Time/Unix/UnixTimeDelta.Compare.cs index aac266c70..72f59f82e 100644 --- a/csharp/lib/Time/Unix/UnixTimeDelta.Compare.cs +++ b/csharp/lib/Time/Unix/UnixTimeDelta.Compare.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTimeSpan : IComparable, IEquatable { diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Constructors.cs b/csharp/lib/Time/Unix/UnixTimeDelta.Constructors.cs index 7811fb4d6..c1fa4f877 100644 --- a/csharp/lib/Time/Unix/UnixTimeDelta.Constructors.cs +++ b/csharp/lib/Time/Unix/UnixTimeDelta.Constructors.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTimeSpan { diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Operators.cs b/csharp/lib/Time/Unix/UnixTimeDelta.Operators.cs index d373ccde1..dc2805e2d 100644 --- a/csharp/lib/Time/Unix/UnixTimeDelta.Operators.cs +++ b/csharp/lib/Time/Unix/UnixTimeDelta.Operators.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTimeSpan { diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Overrides.cs b/csharp/lib/Time/Unix/UnixTimeDelta.Overrides.cs index 0c000fab9..9552fbbe3 100644 --- a/csharp/lib/Time/Unix/UnixTimeDelta.Overrides.cs +++ b/csharp/lib/Time/Unix/UnixTimeDelta.Overrides.cs @@ -1,6 +1,6 @@ using System.Text; -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTimeSpan { diff --git a/csharp/lib/Time/Unix/UnixTimeDeltaExtensions.cs b/csharp/lib/Time/Unix/UnixTimeDeltaExtensions.cs index c51928b98..fd98e3487 100644 --- a/csharp/lib/Time/Unix/UnixTimeDeltaExtensions.cs +++ b/csharp/lib/Time/Unix/UnixTimeDeltaExtensions.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public static class UnixTimeDeltaExtensions { diff --git a/csharp/lib/Time/Unix/UnixTimeSpan.cs b/csharp/lib/Time/Unix/UnixTimeSpan.cs index cb54ae279..d525deaba 100644 --- a/csharp/lib/Time/Unix/UnixTimeSpan.cs +++ b/csharp/lib/Time/Unix/UnixTimeSpan.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Time.Unix; +namespace InnovEnergy.Lib.Time.Unix; public readonly partial struct UnixTimeSpan { diff --git a/csharp/lib/Utils/Utils.csproj b/csharp/lib/Utils/Utils.csproj index 0ddcddea5..222f85663 100644 --- a/csharp/lib/Utils/Utils.csproj +++ b/csharp/lib/Utils/Utils.csproj @@ -2,7 +2,7 @@ - InnovEnergy.Lib.Utils + diff --git a/csharp/lib/Victron/VeDBus/VeDBus.csproj b/csharp/lib/Victron/VeDBus/VeDBus.csproj index 939a409a2..5f986d84c 100644 --- a/csharp/lib/Victron/VeDBus/VeDBus.csproj +++ b/csharp/lib/Victron/VeDBus/VeDBus.csproj @@ -3,7 +3,7 @@ - InnovEnergy.Lib.Victron.VeDBus + latest diff --git a/csharp/lib/Victron/VictronVRM/Installation.cs b/csharp/lib/Victron/VictronVRM/Installation.cs index ba479b0f6..aa233e275 100644 --- a/csharp/lib/Victron/VictronVRM/Installation.cs +++ b/csharp/lib/Victron/VictronVRM/Installation.cs @@ -1,6 +1,6 @@ using System.Text.Json.Nodes; +using InnovEnergy.Lib.Time.Unix; using InnovEnergy.Lib.Utils; -using InnovEnergy.Time.Unix; // ReSharper disable StringLiteralTypo diff --git a/csharp/lib/Victron/VictronVRM/VictronVRM.csproj b/csharp/lib/Victron/VictronVRM/VictronVRM.csproj index d8fe8e6dd..4370080ea 100644 --- a/csharp/lib/Victron/VictronVRM/VictronVRM.csproj +++ b/csharp/lib/Victron/VictronVRM/VictronVRM.csproj @@ -7,7 +7,7 @@ - InnovEnergy.Lib.Victron.VictronVRM + latest diff --git a/csharp/lib/WebServer/WebServer.csproj b/csharp/lib/WebServer/WebServer.csproj index e879bb272..8063be2ce 100644 --- a/csharp/lib/WebServer/WebServer.csproj +++ b/csharp/lib/WebServer/WebServer.csproj @@ -3,7 +3,7 @@ - InnovEnergy.Lib.WebServer + From 5a3ee3d37ebb5d2b36c93d6c854a54d7f2476686 Mon Sep 17 00:00:00 2001 From: ig Date: Sat, 25 Feb 2023 15:56:48 +0100 Subject: [PATCH 010/114] tie namespace and assembly names to directory structure --- csharp/lib/Devices/AMPT/Ampt.csproj | 6 ------ csharp/lib/Devices/Adam6060/Adam6060.csproj | 6 ------ csharp/lib/Devices/Battery48TL/Battery48TL.csproj | 5 ----- csharp/lib/Devices/EmuMeter/EmuMeter.csproj | 5 ----- csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj | 5 ----- .../lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj | 6 +----- .../lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj | 6 ------ csharp/lib/Protocols/DBus/DBus.csproj | 2 -- csharp/lib/Protocols/Modbus/Modbus.csproj | 5 ----- csharp/lib/StatusApi/StatusApi.csproj | 9 --------- 10 files changed, 1 insertion(+), 54 deletions(-) diff --git a/csharp/lib/Devices/AMPT/Ampt.csproj b/csharp/lib/Devices/AMPT/Ampt.csproj index a576a4ee7..2190a3c06 100644 --- a/csharp/lib/Devices/AMPT/Ampt.csproj +++ b/csharp/lib/Devices/AMPT/Ampt.csproj @@ -1,12 +1,6 @@ - - InnovEnergy.Lib.Devices.Ampt - - - - diff --git a/csharp/lib/Devices/Adam6060/Adam6060.csproj b/csharp/lib/Devices/Adam6060/Adam6060.csproj index 9cc351396..de99fbbaa 100644 --- a/csharp/lib/Devices/Adam6060/Adam6060.csproj +++ b/csharp/lib/Devices/Adam6060/Adam6060.csproj @@ -1,12 +1,6 @@ - - InnovEnergy.Lib.Devices.Adam6060 - - - - diff --git a/csharp/lib/Devices/Battery48TL/Battery48TL.csproj b/csharp/lib/Devices/Battery48TL/Battery48TL.csproj index 5007b1d4b..bbfe44b02 100644 --- a/csharp/lib/Devices/Battery48TL/Battery48TL.csproj +++ b/csharp/lib/Devices/Battery48TL/Battery48TL.csproj @@ -1,11 +1,6 @@ - - InnovEnergy.Lib.Devices.Battery48TL - - - diff --git a/csharp/lib/Devices/EmuMeter/EmuMeter.csproj b/csharp/lib/Devices/EmuMeter/EmuMeter.csproj index fc57021a4..bbfe44b02 100644 --- a/csharp/lib/Devices/EmuMeter/EmuMeter.csproj +++ b/csharp/lib/Devices/EmuMeter/EmuMeter.csproj @@ -1,11 +1,6 @@ - - InnovEnergy.Lib.Devices.EmuMeter - - - diff --git a/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj b/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj index ffe741177..660a234b8 100644 --- a/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj +++ b/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj @@ -1,13 +1,8 @@ - - - - - diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj b/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj index 0e28aa423..b29f9d3f8 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj +++ b/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj @@ -1,11 +1,7 @@ - - InnovEnergy.Lib.Devices.Trumpf.TruConvertAc - - latest - + diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj b/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj index 109275eee..8f13140f6 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj +++ b/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj @@ -1,12 +1,6 @@ - - InnovEnergy.Lib.Devices.Trumpf.TruConvertDc - - latest - - diff --git a/csharp/lib/Protocols/DBus/DBus.csproj b/csharp/lib/Protocols/DBus/DBus.csproj index 7a32ff8a1..e33bdceca 100644 --- a/csharp/lib/Protocols/DBus/DBus.csproj +++ b/csharp/lib/Protocols/DBus/DBus.csproj @@ -4,8 +4,6 @@ DBus Library true - InnovEnergy.Lib.Protocols.DBus - diff --git a/csharp/lib/Protocols/Modbus/Modbus.csproj b/csharp/lib/Protocols/Modbus/Modbus.csproj index 18f18b58f..d40e6dc28 100644 --- a/csharp/lib/Protocols/Modbus/Modbus.csproj +++ b/csharp/lib/Protocols/Modbus/Modbus.csproj @@ -1,11 +1,6 @@ - - InnovEnergy.Lib.Protocols.Modbus - - - diff --git a/csharp/lib/StatusApi/StatusApi.csproj b/csharp/lib/StatusApi/StatusApi.csproj index edc182ef8..bb446855b 100644 --- a/csharp/lib/StatusApi/StatusApi.csproj +++ b/csharp/lib/StatusApi/StatusApi.csproj @@ -1,12 +1,6 @@ - - InnovEnergy.Lib.StatusApi - - - - @@ -14,6 +8,3 @@ - - - From aa46ad37b66c827840bec9ab9dfd661e689321ef Mon Sep 17 00:00:00 2001 From: ig Date: Sat, 25 Feb 2023 16:04:41 +0100 Subject: [PATCH 011/114] app => App, lib => Lib --- csharp/{app => App}/Backend/Backend.csproj | 4 +- .../Backend/Controllers/Controller.cs | 0 .../Backend/Controllers/Credentials.cs | 0 .../Backend/Controllers/ReturnsAttribute.cs | 0 csharp/{app => App}/Backend/Database/Db.cs | 0 csharp/{app => App}/Backend/Database/Fake.cs | 0 .../{app => App}/Backend/Database/Folder.cs | 0 .../Backend/Database/Installation.cs | 0 csharp/{app => App}/Backend/Database/User.cs | 0 .../Backend/Database/User2Folder.cs | 0 .../Backend/Database/User2Installation.cs | 0 csharp/{app => App}/Backend/FakeFolders.csv | 0 .../Backend/FakeInstallations.csv | 0 csharp/{app => App}/Backend/FakePasswords.csv | 0 csharp/{app => App}/Backend/FakeUsers.csv | 0 csharp/{app => App}/Backend/HeaderFilter.cs | 0 csharp/{app => App}/Backend/Model/Folder.cs | 0 .../Backend/Model/Installation.cs | 0 .../Backend/Model/Relations/Relation.cs | 0 .../Backend/Model/Relations/Session.cs | 0 .../Backend/Model/Relations/User2Folder.cs | 0 .../Model/Relations/User2Installation.cs | 0 .../Backend/Model/TreeNode.Equality.cs | 0 csharp/{app => App}/Backend/Model/TreeNode.cs | 0 csharp/{app => App}/Backend/Model/User.cs | 0 csharp/{app => App}/Backend/Program.cs | 0 .../Backend/Properties/launchSettings.json | 0 csharp/{app => App}/Backend/Utils/Crypto.cs | 0 csharp/{app => App}/Backend/Utils/Result.cs | 0 csharp/App/Backend/db.sqlite | Bin 0 -> 290816 bytes .../BmsTunnel/BatteryConnection.cs | 0 csharp/{app => App}/BmsTunnel/BmsTunnel.cs | 0 .../{app => App}/BmsTunnel/BmsTunnel.csproj | 4 +- csharp/{app => App}/BmsTunnel/CliPrograms.cs | 0 csharp/{app => App}/BmsTunnel/Program.cs | 0 csharp/{app => App}/BmsTunnel/debug.sh | 0 csharp/{app => App}/BmsTunnel/parameters.txt | 0 .../{app => App}/Collector/Collector.csproj | 6 +- csharp/{app => App}/Collector/Collector.sln | 0 .../Collector/src/BatteryDataParser.cs | 0 .../Collector/src/BatteryDataParserV4.cs | 0 .../Collector/src/Influx/FieldAttribute.cs | 0 .../Collector/src/Influx/InfluxRecord.cs | 0 .../src/Influx/LineProtocolSyntax.cs | 0 .../Collector/src/Influx/TagAttribute.cs | 0 csharp/{app => App}/Collector/src/Program.cs | 0 .../Collector/src/Records/Alarms.cs | 0 .../Collector/src/Records/BatteryRecord.cs | 0 .../Collector/src/Records/BatteryStatus.cs | 0 .../Collector/src/Records/Error.cs | 0 .../src/Records/InstallationStatus.cs | 0 .../Collector/src/Records/IoStatus.cs | 0 .../Collector/src/Records/Leds.cs | 0 .../Collector/src/Records/Temperatures.cs | 0 .../Collector/src/Records/Warnings.cs | 0 csharp/{app => App}/Collector/src/Settings.cs | 0 .../Collector/src/Utils/Extensions.cs | 0 .../{app => App}/Collector/src/Utils/Log.cs | 0 .../Collector/src/Utils/Property.cs | 0 .../src/Utils/ReadOnlyListExtensions.cs | 0 .../{app => App}/Collector/src/Utils/Utils.cs | 0 csharp/{app => App}/EmuMeterDriver/Config.cs | 0 .../EmuMeterDriver/EmuMeterDriver.cs | 0 .../App/EmuMeterDriver/EmuMeterDriver.csproj | 16 +++++ csharp/{app => App}/EmuMeterDriver/Nic.cs | 0 csharp/{app => App}/EmuMeterDriver/Program.cs | 0 csharp/{app => App}/EmuMeterDriver/Signal.cs | 0 csharp/{app => App}/EmuMeterDriver/Utils.cs | 0 csharp/{app => App}/EmuMeterDriver/debug.sh | 0 .../EmuMeterDriver/service/log/run | 0 .../{app => App}/EmuMeterDriver/service/run | 0 .../InnovEnergy.App.props} | 0 .../OpenVpnCertificatesServer/Files.cs | 0 .../OpenVpnCertificatesServer/Http.cs | 0 .../OpenVpnCertificatesServer.csproj | 7 ++- .../OpenVpnCertificatesServer.sln | 0 .../PKI/CertificateAuthority.cs | 0 .../OpenVpnCertificatesServer/PKI/Pem.cs | 0 .../PKI/PwdFinder.cs | 0 .../OpenVpnCertificatesServer/Program.cs | 0 .../OpenVpnCertificatesServer/Utils.cs | 0 .../RemoteSupportConsole/Login.cs | 0 .../ObservablePipeSource.cs | 0 .../RemoteSupportConsole/Program.cs | 0 .../RemoteSupportConsole.csproj | 6 +- .../RemoteSupportConsole.csproj.DotSettings | 0 .../{app => App}/RemoteSupportConsole/Ssh.cs | 0 .../RemoteSupportConsole/VpnConnection.cs | 0 .../RemoteSupportConsole/VpnInfo.cs | 0 .../RemoteSupportConsole/VrmConnection.cs | 0 .../RemoteSupportConsole/VrmInfo.cs | 0 .../RemoteSupportConsole/VrmProxy.cs | 0 csharp/App/SaliMax/SaliMax.csproj | 25 ++++++++ .../SaliMax/run (BeagleBone Meiringen).sh | 0 csharp/{app => App}/SaliMax/src/AsciiArt.cs | 0 csharp/{app => App}/SaliMax/src/BusPort.cs | 0 .../src/Controller/AvgBatteriesStatus.cs | 0 .../SaliMax/src/Controller/Control.cs | 0 .../SaliMax/src/Controller/ControlRecord.cs | 0 .../SaliMax/src/Controller/ControlTarget.cs | 0 .../SaliMax/src/Controller/Controller.cs | 0 .../SaliMax/src/Controller/SaliMaxState.cs | 0 .../SaliMax/src/Controller/State.cs | 0 .../SaliMax/src/Controller/StateConfig.cs | 0 .../SaliMax/src/Controller/StatusRecord.cs | 0 csharp/{app => App}/SaliMax/src/Log/Ampt.cs | 0 .../SaliMax/src/Log/Battery48Tl.cs | 0 .../{app => App}/SaliMax/src/Log/EmuMeter.cs | 0 .../{app => App}/SaliMax/src/Log/JsonUtil.cs | 0 .../{app => App}/SaliMax/src/Log/Salimax.cs | 0 .../SaliMax/src/Log/TruConvertAc.cs | 0 .../SaliMax/src/Log/TruConvertDc.cs | 0 csharp/{app => App}/SaliMax/src/Program.cs | 0 csharp/{app => App}/SaliMax/src/S3Config.cs | 0 .../src/SaliMaxRelays/RelayMapBoolean.cs | 0 .../src/SaliMaxRelays/SaliMaxRelaysDevice.cs | 0 .../src/SaliMaxRelays/SaliMaxRelaysStatus.cs | 0 .../SaliMax/src/SystemConfig/Config.cs | 0 .../SaliMax/src/SystemConfig/Defaults.cs | 0 .../SaliMax/src/SystemConfig/SalimaxConfig.cs | 0 csharp/{app => App}/SaliMax/src/Topology.cs | 0 csharp/{app => App}/SaliMax/src/Utils.cs | 0 csharp/{app => App}/SaliMax/tunnels.html | 0 csharp/{app => App}/SaliMax/tunnels.sh | 0 csharp/InnovEnergy.sln | 56 +++++++++--------- csharp/Lib/Channels/Channels.csproj | 9 +++ csharp/{lib => Lib}/Channels/CloseAfter.cs | 0 csharp/{lib => Lib}/Channels/Connection.cs | 0 .../{lib => Lib}/Channels/Framed/Channel.cs | 0 .../{lib => Lib}/Channels/Stages/Channel.cs | 0 .../Channels/Stages/ConnectedChannel.cs | 0 csharp/{lib => Lib}/Channels/Stages/Stage.cs | 0 .../Channels/V2/Bak/Connections/Connection.cs | 0 .../V2/Bak/Connections/Connections.cs | 0 .../Channels/V2/Bak/Connections/Extensions.cs | 0 .../V2/Bak/Connections/IConnection.cs | 0 .../Channels/V2/Bak/GenericChannel.cs | 0 .../Channels/V2/Bak/StreamChannel.cs | 0 .../Channels/V2/CommandChannel.cs | 0 csharp/{lib => Lib}/Channels/V2/IChannel.cs | 0 .../Channels/V2/Pipes/AsyncPipeSource.cs | 0 .../Channels/V2/Pipes/AsyncPipeTarget.cs | 0 .../Channels/V2/Pipes/ChannelPipeSource.cs | 0 .../Channels/V2/Pipes/ChannelPipeTarget.cs | 0 csharp/{lib => Lib}/Channels/V2/Stage.cs | 0 .../{lib => Lib}/Channels/V2/StreamChannel.cs | 0 csharp/{lib => Lib}/Channels/V2/TcpChannel.cs | 0 csharp/{lib => Lib}/Devices/AMPT/Ampt.csproj | 2 +- .../Devices/AMPT/AmptCommunicationUnit.cs | 0 .../Devices/AMPT/AmptDeviceStatus.cs | 0 .../{lib => Lib}/Devices/AMPT/AmptStatus.cs | 0 .../Devices/AMPT/AmptStringStatus.cs | 0 .../Devices/Adam6060/Adam6060.csproj | 2 +- .../Devices/Adam6060/Adam6060Control.cs | 0 .../Devices/Adam6060/Adam6060Device.cs | 0 .../Devices/Adam6060/Adam6060Status.cs | 0 .../Devices/Battery48TL/Battery48TL.csproj | 2 +- .../Devices/Battery48TL/Battery48TLDevice.cs | 0 .../Battery48TL/Battery48TLStatusRecord.cs | 0 .../Devices/Battery48TL/BatteryDataParser.cs | 0 .../Devices/Battery48TL/Constants.cs | 0 .../Devices/Battery48TL/LedColor.cs | 0 .../Devices/Battery48TL/LedState.cs | 0 .../Devices/EmuMeter/Conversions.cs | 0 .../Devices/EmuMeter/EmuMeter.csproj | 2 +- .../Devices/EmuMeter/EmuMeterDevice.cs | 0 .../Devices/EmuMeter/EmuMeterStatus.cs | 0 .../Devices/Trumpf/TruConvert/AlarmState.cs | 0 .../Devices/Trumpf/TruConvert/MainState.cs | 0 .../Devices/Trumpf/TruConvert/Slave.cs | 0 .../Devices/Trumpf/TruConvert/SystemConfig.cs | 0 .../Trumpf/TruConvert/TruConvert.csproj | 2 +- .../Devices/Trumpf/TruConvert/Utils.cs | 0 .../Trumpf/TruConvertAc/AcControlRegisters.cs | 0 .../Devices/Trumpf/TruConvertAc/AcEnums.cs | 0 .../Trumpf/TruConvertAc/AlarmMessage.cs | 0 .../Trumpf/TruConvertAc/TruConvertAc.csproj | 2 +- .../TruConvertAc/TruConvertAcControl.cs | 0 .../Trumpf/TruConvertAc/TruConvertAcDevice.cs | 0 .../Trumpf/TruConvertAc/TruConvertAcStatus.cs | 0 .../Trumpf/TruConvertAc/WarningMessage.cs | 0 .../Trumpf/TruConvertDc/AlarmMessage.cs | 0 .../Trumpf/TruConvertDc/DcControlRegisters.cs | 0 .../Devices/Trumpf/TruConvertDc/DcEnums.cs | 0 .../Trumpf/TruConvertDc/TruConvertDc.csproj | 2 +- .../TruConvertDc/TruConvertDcControl.cs | 0 .../Trumpf/TruConvertDc/TruConvertDcDevice.cs | 0 .../Trumpf/TruConvertDc/TruConvertDcStatus.cs | 0 .../Trumpf/TruConvertDc/WarningMessage.cs | 0 .../InnovEnergy.Lib.props} | 0 csharp/{lib => Lib}/Protocols/DBus/Bus.cs | 0 .../{lib => Lib}/Protocols/DBus/DBus.csproj | 2 +- .../Protocols/DBus/DBusConnection.cs | 0 .../Protocols/DBus/DBusMessageStream.cs | 0 .../Protocols/DBus/DBusService.cs | 0 .../Protocols/DBus/Daemon/DBusDaemonApi.cs | 0 .../Daemon/DBusDaemonConnection.Resolver.cs | 0 .../DBus/Daemon/DBusDaemonConnection.cs | 0 .../Protocols/DBus/Daemon/MatchRule.cs | 0 .../DBus/Daemon/ObservableDictionary.cs | 0 .../Protocols/DBus/Daemon/ReleaseNameReply.cs | 0 .../DBus/Daemon/RequestNameOptions.cs | 0 .../Protocols/DBus/Daemon/RequestNameReply.cs | 0 csharp/{lib => Lib}/Protocols/DBus/Env.cs | 0 csharp/{lib => Lib}/Protocols/DBus/Interop.cs | 0 .../DataTypes/Convert/StringToSignature.cs | 0 .../DataTypes/Convert/TypeToSignature.cs | 0 .../DBus/Protocol/DataTypes/ObjectPath.cs | 0 .../Signatures/Signature.Equality.cs | 0 .../Signatures/Signature.Terminals.cs | 0 .../DataTypes/Signatures/Signature.cs | 0 .../Signatures/Specialized/ArraySignature.cs | 0 .../Specialized/BasicTypeSignature.cs | 0 .../Specialized/BooleanSignature.cs | 0 .../Signatures/Specialized/ByteSignature.cs | 0 .../Specialized/CompositeSignature.cs | 0 .../Specialized/ContainerTypeSignature.cs | 0 .../Specialized/DictionarySignature.cs | 0 .../Signatures/Specialized/DoubleSignature.cs | 0 .../Signatures/Specialized/EmptySignature.cs | 0 .../Specialized/FixedTypeSignature.cs | 0 .../Signatures/Specialized/Int16Signature.cs | 0 .../Signatures/Specialized/Int32Signature.cs | 0 .../Signatures/Specialized/Int64Signature.cs | 0 .../Specialized/ObjectPathSignature.cs | 0 .../Specialized/SignatureTypeSignature.cs | 0 .../Specialized/StringLikeTypeSignature.cs | 0 .../Signatures/Specialized/StringSignature.cs | 0 .../Signatures/Specialized/StructSignature.cs | 0 .../Signatures/Specialized/UInt16Signature.cs | 0 .../Signatures/Specialized/UInt32Signature.cs | 0 .../Signatures/Specialized/UInt64Signature.cs | 0 .../Specialized/VariantSignature.cs | 0 .../DBus/Protocol/DataTypes/Variant.cs | 0 .../Protocols/DBus/Protocol/Header/Endian.cs | 0 .../DBus/Protocol/Header/FieldCode.cs | 0 .../DBus/Protocol/Header/HeaderExtensions.cs | 0 .../DBus/Protocol/Header/HeaderFlags.cs | 0 .../DBus/Protocol/Header/MessageType.cs | 0 .../Protocols/DBus/Protocol/Message.cs | 0 .../Protocols/DBus/Protocol/Replies.cs | 0 .../Protocols/DBus/Protocol/SerialSource.cs | 0 .../DBus/Transport/AuthenticationMethod.cs | 0 .../DBus/Transport/BufferedSocketReader.cs | 0 .../DBus/Transport/DBusBufferReader.cs | 0 .../DBus/Transport/DBusBufferWriter.cs | 0 .../Protocols/DBus/Transport/DBusSocket.cs | 0 .../Protocols/DBus/Utils/DisposableStack.cs | 0 .../Protocols/DBus/Utils/Extensions.cs | 0 .../Protocols/DBus/Utils/HexView.cs | 0 .../DBus/WireFormat/DBusMeasureWriter.cs | 0 .../Protocols/DBus/WireFormat/DBusReader.cs | 0 .../DBus/WireFormat/DBusSocketReader.cs | 0 .../Protocols/DBus/WireFormat/DBusWriter.cs | 0 .../Protocols/Modbus/Clients/ModbusClient.cs | 0 .../Modbus/Clients/ModbusRtuClient.cs | 0 .../Modbus/Clients/ModbusTcpClient.cs | 0 .../Modbus/Connections/ModbusConnection.cs | 0 .../Connections/ModbusSerialConnection.cs | 0 .../Modbus/Connections/ModbusTcpConnection.cs | 0 .../Modbus/Conversions/Endianness.cs | 0 .../Modbus/Conversions/ModbusRegisters.Bit.cs | 0 .../Conversions/ModbusRegisters.Boolean.cs | 0 .../Conversions/ModbusRegisters.Bytes.cs | 0 .../Conversions/ModbusRegisters.Int16.cs | 0 .../Conversions/ModbusRegisters.Int32.cs | 0 .../Conversions/ModbusRegisters.Single.cs | 0 .../Conversions/ModbusRegisters.String.cs | 0 .../Conversions/ModbusRegisters.UInt16.cs | 0 .../Conversions/ModbusRegisters.UInt32.cs | 0 .../Modbus/Conversions/ModbusRegisters.cs | 0 .../Protocols/Modbus/Modbus.csproj | 2 +- .../Modbus/Protocol/ExceptionCode.cs | 0 .../Protocols/Modbus/Protocol/Exceptions.cs | 0 .../Protocol/Frames/Accessors/Accessors.cs | 0 .../Protocol/Frames/Accessors/MbAddress.cs | 0 .../Protocol/Frames/Accessors/MbBits.cs | 0 .../Protocol/Frames/Accessors/MbByte.cs | 0 .../Protocol/Frames/Accessors/MbByte{T}.cs | 0 .../Protocol/Frames/Accessors/MbWord.cs | 0 .../Protocol/Frames/Accessors/MbWords.cs | 0 .../ReadDiscreteInputsCommandFrame.cs | 0 .../ReadHoldingRegistersCommandFrame.cs | 0 .../ReadInputRegistersCommandFrame.cs | 0 .../ReadWriteRegistersCommandFrame.cs | 0 .../Frames/Commands/WriteCoilsCommandFrame.cs | 0 .../Commands/WriteRegistersCommandFrame.cs | 0 .../Modbus/Protocol/Frames/Constants.cs | 0 .../Modbus/Protocol/Frames/ModbusFrame.cs | 0 .../Frames/Replies/ErrorResponseFrame.cs | 0 .../Replies/ReadDiscreteInputResponseFrame.cs | 0 .../ReadHoldingRegistersResponseFrame.cs | 0 .../ReadInputRegistersResponseFrame.cs | 0 .../Replies/ReadWriteRegistersCommandFrame.cs | 0 .../Frames/Replies/WriteCoilsResponseFrame.cs | 0 .../Replies/WriteRegistersResponseFrame.cs | 0 .../Protocols/Modbus/Protocol/FunctionCode.cs | 0 .../Protocols/Modbus/Tcp/MbapHeader.cs | 0 .../Protocols/Modbus/Tcp/ModbusTcpFrame.cs | 0 .../Modbus/Util/ArraySegmentExtensions.cs | 0 csharp/{lib => Lib}/S3/DataRec.cs | 0 .../Drivers/Internal/Delegates/ReadRecord.cs | 0 .../Drivers/Internal/Delegates/WriteRecord.cs | 0 .../S3/Drivers/Internal/Reader.cs | 0 .../S3/Drivers/Internal/Reader.public.cs | 0 .../S3/Drivers/Internal/Util/Aggregator.cs | 0 .../S3/Drivers/Internal/Util/Sampler.cs | 0 .../S3/Drivers/Internal/Writer.cs | 0 .../S3/Drivers/Internal/Writer.public.cs | 0 .../{lib => Lib}/S3/Drivers/MemoryDriver.cs | 0 csharp/{lib => Lib}/S3/Drivers/S3Config.cs | 0 csharp/{lib => Lib}/S3/Drivers/S3Driver.cs | 0 .../S3/Metadata/AggregationLevel.cs | 0 csharp/{lib => Lib}/S3/Metadata/FieldType.cs | 0 csharp/{lib => Lib}/S3/Program.cs | 0 .../{lib => Lib}/S3/Records/Fields/Field.cs | 0 .../S3/Records/Fields/NumberField.cs | 0 .../S3/Records/Fields/TextField.cs | 0 .../S3/Records/Fields/TextFrequency.cs | 0 .../S3/Records/Fields/UnitAttribute.cs | 0 .../S3/Records/Fields/WithUnit.cs | 0 .../S3/Records/Operations/Aggregation.cs | 0 .../S3/Records/Operations/Conversion.cs | 0 csharp/{lib => Lib}/S3/Records/Record.cs | 0 .../S3/Records/Serialization/FieldTag.cs | 0 .../S3/Records/Serialization/Parser.cs | 0 .../S3/Records/Serialization/Serializer.cs | 0 .../Records/Specialized/AggregatedRecord.cs | 0 .../Records/Specialized/TimeStampedRecord.cs | 0 csharp/{lib => Lib}/S3/S3.csproj | 6 +- .../S3/Serialization/JsonConverters.cs | 0 .../StatusApi/Connections/DcConnection.cs | 0 .../Connections/SinglePhaseAcConnection.cs | 0 .../Connections/ThreePhaseAcConnection.cs | 0 csharp/{lib => Lib}/StatusApi/DeviceType.cs | 0 .../{lib => Lib}/StatusApi/Devices/Battery.cs | 0 .../StatusApi/Devices/DcDcConverter.cs | 0 .../StatusApi/Devices/DcDevice.cs | 0 .../{lib => Lib}/StatusApi/Devices/Device.cs | 0 .../StatusApi/Devices/GridMeter.cs | 0 .../StatusApi/Devices/IPvCoupledDevice.cs | 0 csharp/{lib => Lib}/StatusApi/Devices/Mppt.cs | 0 .../StatusApi/Devices/SinglePhaseAcDevice.cs | 0 .../StatusApi/Devices/SinglePhaseInverter.cs | 0 .../Devices/SinglePhasePvInverter.cs | 0 .../StatusApi/Devices/ThreePhaseAcDevice.cs | 0 .../StatusApi/Devices/ThreePhaseInverter.cs | 0 .../StatusApi/Devices/ThreePhasePvInverter.cs | 0 .../{lib => Lib}/StatusApi/Phases/AcPhase.cs | 0 csharp/{lib => Lib}/StatusApi/Phases/Phase.cs | 0 .../{lib => Lib}/StatusApi/StatusApi.csproj | 2 +- csharp/{lib => Lib}/StatusApi/Utils.cs | 0 csharp/{lib => Lib}/StatusData/Current.cs | 0 .../StatusData/Json/Converters.cs | 0 .../StatusData/Json/CurrentConverter.cs | 0 .../StatusData/Json/PowerConverter.cs | 0 .../StatusData/Json/ResistanceConverter.cs | 0 .../StatusData/Json/VoltageConverter.cs | 0 csharp/{lib => Lib}/StatusData/Power.cs | 0 csharp/{lib => Lib}/StatusData/Resistance.cs | 0 csharp/{lib => Lib}/StatusData/State.cs | 0 .../{lib => Lib}/StatusData/StatusData.csproj | 2 +- csharp/{lib => Lib}/StatusData/Units.cs | 0 csharp/{lib => Lib}/StatusData/Voltage.cs | 0 .../SysTools/Edges/RemoteCommandToProcess.cs | 0 .../Edges/RemotePathToRemoteCommand.cs | 0 .../SysTools/Edges/SshHostToRemoteCommand.cs | 0 .../SysTools/Edges/SshHostToRemotePath.cs | 0 .../SysTools/Edges/StringToCommand.cs | 0 .../SysTools/Edges/StringToProcess.cs | 0 .../SysTools/Edges/StringToRemotePath.cs | 0 .../SysTools/Edges/StringToSysPath.cs | 0 .../SysTools/Edges/SysCommandToProcess.cs | 0 .../Edges/SysCommandToRemoteCommand.cs | 0 .../SysTools/Edges/SysPathToProcess.cs | 0 .../SysTools/Edges/SysPathToRemotePath.cs | 0 .../SysTools/Edges/SysPathToSysCommand.cs | 0 csharp/{lib => Lib}/SysTools/FileIo.cs | 0 .../SysTools/Process/AsyncProcess.cs | 0 .../SysTools/Process/ProcessResult.cs | 0 .../SysTools/Process/SyncProcess.cs | 0 .../SysTools/Remote/RemoteCommand.cs | 0 .../SysTools/Remote/RemoteFileIo.cs | 0 .../SysTools/Remote/RemotePath.cs | 0 .../{lib => Lib}/SysTools/Remote/SshHost.cs | 0 csharp/{lib => Lib}/SysTools/SysCommand.cs | 0 csharp/{lib => Lib}/SysTools/SysDirs.cs | 0 csharp/{lib => Lib}/SysTools/SysPath.cs | 0 csharp/{lib => Lib}/SysTools/SysTools.csproj | 2 +- .../SysTools/Utils/ConsoleUtils.cs | 0 .../SysTools/Utils/EnumerableUtils.cs | 0 .../SysTools/Utils/StringUtils.cs | 0 csharp/{lib => Lib}/SysTools/Utils/Utils.cs | 0 csharp/Lib/Time/Time.csproj | 3 + .../Time/Unix/UnixTime.Compare.cs | 0 .../Time/Unix/UnixTime.Constructors.cs | 0 .../Time/Unix/UnixTime.Converters.cs | 0 .../Time/Unix/UnixTime.Operators.cs | 0 .../Time/Unix/UnixTime.Overrides.cs | 0 csharp/{lib => Lib}/Time/Unix/UnixTime.cs | 0 .../Time/Unix/UnixTimeDelta.Compare.cs | 0 .../Time/Unix/UnixTimeDelta.Constructors.cs | 0 .../Time/Unix/UnixTimeDelta.Operators.cs | 0 .../Time/Unix/UnixTimeDelta.Overrides.cs | 0 .../Time/Unix/UnixTimeDeltaExtensions.cs | 0 csharp/{lib => Lib}/Time/Unix/UnixTimeSpan.cs | 0 csharp/{lib => Lib}/Utils/ArrayExtensions.cs | 0 csharp/{lib => Lib}/Utils/AsyncDelegates.cs | 0 .../{lib => Lib}/Utils/AsyncEnumerableEx.cs | 0 csharp/{lib => Lib}/Utils/AutoComplete.cs | 0 csharp/{lib => Lib}/Utils/CliCommandUtils.cs | 0 csharp/{lib => Lib}/Utils/ConsoleUtils.cs | 0 csharp/{lib => Lib}/Utils/DecimalUtils.cs | 0 csharp/{lib => Lib}/Utils/DictObservables.cs | 0 csharp/{lib => Lib}/Utils/Disposable.cs | 0 csharp/{lib => Lib}/Utils/EnumerableUtils.cs | 0 .../{lib => Lib}/Utils/ExceptionHandling.cs | 0 csharp/{lib => Lib}/Utils/FileSystem.cs | 0 .../{lib => Lib}/Utils/JsonNodeAccessors.cs | 0 csharp/{lib => Lib}/Utils/Maybe.cs | 0 csharp/{lib => Lib}/Utils/Net/NetUtils.cs | 0 .../{lib => Lib}/Utils/Net/PingExtensions.cs | 0 .../{lib => Lib}/Utils/Net/UdpExtensions.cs | 0 csharp/{lib => Lib}/Utils/None.cs | 0 csharp/{lib => Lib}/Utils/NullableUtils.cs | 0 .../Utils/ObservableExceptionHandling.cs | 0 csharp/{lib => Lib}/Utils/ObservableUtils.cs | 0 csharp/{lib => Lib}/Utils/PointFree.cs | 0 csharp/{lib => Lib}/Utils/SshHost.cs | 0 csharp/{lib => Lib}/Utils/StreamExtensions.cs | 0 csharp/{lib => Lib}/Utils/StringUtils.cs | 0 csharp/{lib => Lib}/Utils/TaskUtils.cs | 0 csharp/{lib => Lib}/Utils/TextBlock.cs | 0 .../{lib => Lib}/Utils/Try/Operators.async.cs | 0 .../{lib => Lib}/Utils/Try/Operators.sync.cs | 0 csharp/{lib => Lib}/Utils/Try/Policy.cs | 0 .../{lib => Lib}/Utils/Try/TryAsync.async.cs | 0 csharp/{lib => Lib}/Utils/Try/TryAsync.cs | 0 .../{lib => Lib}/Utils/Try/TryAsync.sync.cs | 0 .../{lib => Lib}/Utils/Try/TrySync.async.cs | 0 csharp/{lib => Lib}/Utils/Try/TrySync.cs | 0 csharp/{lib => Lib}/Utils/Try/TrySync.sync.cs | 0 csharp/{lib => Lib}/Utils/Units.cs | 0 csharp/{lib => Lib}/Utils/Utils.cs | 0 csharp/{lib => Lib}/Utils/Utils.csproj | 2 +- csharp/{lib => Lib}/Utils/Utils.sln | 0 csharp/{lib => Lib}/Utils/ValueTupleUtils.cs | 0 csharp/{lib => Lib}/Victron/VeDBus/Program.cs | 0 csharp/{lib => Lib}/Victron/VeDBus/VeDBus.cs | 0 .../{lib => Lib}/Victron/VeDBus/VeDBus.csproj | 2 +- .../{lib => Lib}/Victron/VeDBus/VeDBusApi.cs | 0 .../Victron/VeDBus/VeDbusService.cs | 0 .../Victron/VeDBus/VeProperties.Dbus.cs | 0 .../Victron/VeDBus/VeProperties.cs | 0 .../{lib => Lib}/Victron/VeDBus/VeProperty.cs | 0 .../{lib => Lib}/Victron/VictronVRM/Detail.cs | 0 .../Victron/VictronVRM/Details.cs | 0 .../{lib => Lib}/Victron/VictronVRM/Device.cs | 0 .../Victron/VictronVRM/FlurlExtensions.cs | 0 .../VictronVRM/Installation.Settings.cs | 0 .../Victron/VictronVRM/Installation.Tags.cs | 0 .../Victron/VictronVRM/Installation.cs | 0 .../{lib => Lib}/Victron/VictronVRM/Reply.cs | 0 .../Victron/VictronVRM/Requests.cs | 0 .../Victron/VictronVRM/Settings.cs | 0 .../Victron/VictronVRM/VictronVRM.csproj | 2 +- .../Victron/VictronVRM/VrmAccount.cs | 0 csharp/{lib => Lib}/WebServer/ContentType.cs | 0 csharp/{lib => Lib}/WebServer/Default.cs | 0 .../{lib => Lib}/WebServer/HttpExtensions.cs | 0 csharp/{lib => Lib}/WebServer/HttpHeader.cs | 0 csharp/{lib => Lib}/WebServer/HttpMethod.cs | 0 csharp/{lib => Lib}/WebServer/HttpRequest.cs | 0 csharp/{lib => Lib}/WebServer/HttpResponse.cs | 0 csharp/{lib => Lib}/WebServer/WebServer.cs | 0 .../{lib => Lib}/WebServer/WebServer.csproj | 4 +- .../Wireformat/WireFormat.csproj.DotSettings | 0 csharp/{lib => Lib}/Wireformat/build_proto.sh | 0 .../{lib => Lib}/Wireformat/package-lock.json | 0 csharp/{lib => Lib}/Wireformat/package.json | 0 .../Wireformat/proto/Payload.proto | 0 .../proto/VictronV1/BatteryStatus48TL.proto | 0 .../Wireformat/proto/VictronV1/Device.proto | 0 .../proto/VictronV1/VictronTopologyV1.proto | 0 csharp/app/Backend/db.sqlite | Bin 290816 -> 0 bytes .../app/EmuMeterDriver/EmuMeterDriver.csproj | 16 ----- csharp/app/SaliMax/SaliMax.csproj | 25 -------- csharp/lib/Channels/Channels.csproj | 9 --- csharp/lib/Time/Time.csproj | 3 - 489 files changed, 115 insertions(+), 114 deletions(-) rename csharp/{app => App}/Backend/Backend.csproj (93%) rename csharp/{app => App}/Backend/Controllers/Controller.cs (100%) rename csharp/{app => App}/Backend/Controllers/Credentials.cs (100%) rename csharp/{app => App}/Backend/Controllers/ReturnsAttribute.cs (100%) rename csharp/{app => App}/Backend/Database/Db.cs (100%) rename csharp/{app => App}/Backend/Database/Fake.cs (100%) rename csharp/{app => App}/Backend/Database/Folder.cs (100%) rename csharp/{app => App}/Backend/Database/Installation.cs (100%) rename csharp/{app => App}/Backend/Database/User.cs (100%) rename csharp/{app => App}/Backend/Database/User2Folder.cs (100%) rename csharp/{app => App}/Backend/Database/User2Installation.cs (100%) rename csharp/{app => App}/Backend/FakeFolders.csv (100%) rename csharp/{app => App}/Backend/FakeInstallations.csv (100%) rename csharp/{app => App}/Backend/FakePasswords.csv (100%) rename csharp/{app => App}/Backend/FakeUsers.csv (100%) rename csharp/{app => App}/Backend/HeaderFilter.cs (100%) rename csharp/{app => App}/Backend/Model/Folder.cs (100%) rename csharp/{app => App}/Backend/Model/Installation.cs (100%) rename csharp/{app => App}/Backend/Model/Relations/Relation.cs (100%) rename csharp/{app => App}/Backend/Model/Relations/Session.cs (100%) rename csharp/{app => App}/Backend/Model/Relations/User2Folder.cs (100%) rename csharp/{app => App}/Backend/Model/Relations/User2Installation.cs (100%) rename csharp/{app => App}/Backend/Model/TreeNode.Equality.cs (100%) rename csharp/{app => App}/Backend/Model/TreeNode.cs (100%) rename csharp/{app => App}/Backend/Model/User.cs (100%) rename csharp/{app => App}/Backend/Program.cs (100%) rename csharp/{app => App}/Backend/Properties/launchSettings.json (100%) rename csharp/{app => App}/Backend/Utils/Crypto.cs (100%) rename csharp/{app => App}/Backend/Utils/Result.cs (100%) create mode 100644 csharp/App/Backend/db.sqlite rename csharp/{app => App}/BmsTunnel/BatteryConnection.cs (100%) rename csharp/{app => App}/BmsTunnel/BmsTunnel.cs (100%) rename csharp/{app => App}/BmsTunnel/BmsTunnel.csproj (68%) rename csharp/{app => App}/BmsTunnel/CliPrograms.cs (100%) rename csharp/{app => App}/BmsTunnel/Program.cs (100%) rename csharp/{app => App}/BmsTunnel/debug.sh (100%) rename csharp/{app => App}/BmsTunnel/parameters.txt (100%) rename csharp/{app => App}/Collector/Collector.csproj (52%) rename csharp/{app => App}/Collector/Collector.sln (100%) rename csharp/{app => App}/Collector/src/BatteryDataParser.cs (100%) rename csharp/{app => App}/Collector/src/BatteryDataParserV4.cs (100%) rename csharp/{app => App}/Collector/src/Influx/FieldAttribute.cs (100%) rename csharp/{app => App}/Collector/src/Influx/InfluxRecord.cs (100%) rename csharp/{app => App}/Collector/src/Influx/LineProtocolSyntax.cs (100%) rename csharp/{app => App}/Collector/src/Influx/TagAttribute.cs (100%) rename csharp/{app => App}/Collector/src/Program.cs (100%) rename csharp/{app => App}/Collector/src/Records/Alarms.cs (100%) rename csharp/{app => App}/Collector/src/Records/BatteryRecord.cs (100%) rename csharp/{app => App}/Collector/src/Records/BatteryStatus.cs (100%) rename csharp/{app => App}/Collector/src/Records/Error.cs (100%) rename csharp/{app => App}/Collector/src/Records/InstallationStatus.cs (100%) rename csharp/{app => App}/Collector/src/Records/IoStatus.cs (100%) rename csharp/{app => App}/Collector/src/Records/Leds.cs (100%) rename csharp/{app => App}/Collector/src/Records/Temperatures.cs (100%) rename csharp/{app => App}/Collector/src/Records/Warnings.cs (100%) rename csharp/{app => App}/Collector/src/Settings.cs (100%) rename csharp/{app => App}/Collector/src/Utils/Extensions.cs (100%) rename csharp/{app => App}/Collector/src/Utils/Log.cs (100%) rename csharp/{app => App}/Collector/src/Utils/Property.cs (100%) rename csharp/{app => App}/Collector/src/Utils/ReadOnlyListExtensions.cs (100%) rename csharp/{app => App}/Collector/src/Utils/Utils.cs (100%) rename csharp/{app => App}/EmuMeterDriver/Config.cs (100%) rename csharp/{app => App}/EmuMeterDriver/EmuMeterDriver.cs (100%) create mode 100644 csharp/App/EmuMeterDriver/EmuMeterDriver.csproj rename csharp/{app => App}/EmuMeterDriver/Nic.cs (100%) rename csharp/{app => App}/EmuMeterDriver/Program.cs (100%) rename csharp/{app => App}/EmuMeterDriver/Signal.cs (100%) rename csharp/{app => App}/EmuMeterDriver/Utils.cs (100%) rename csharp/{app => App}/EmuMeterDriver/debug.sh (100%) rename csharp/{app => App}/EmuMeterDriver/service/log/run (100%) rename csharp/{app => App}/EmuMeterDriver/service/run (100%) rename csharp/{app/InnovEnergy.app.props => App/InnovEnergy.App.props} (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/Files.cs (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/Http.cs (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj (58%) rename csharp/{app => App}/OpenVpnCertificatesServer/OpenVpnCertificatesServer.sln (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/PKI/Pem.cs (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/PKI/PwdFinder.cs (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/Program.cs (100%) rename csharp/{app => App}/OpenVpnCertificatesServer/Utils.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/Login.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/ObservablePipeSource.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/Program.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/RemoteSupportConsole.csproj (67%) rename csharp/{app => App}/RemoteSupportConsole/RemoteSupportConsole.csproj.DotSettings (100%) rename csharp/{app => App}/RemoteSupportConsole/Ssh.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/VpnConnection.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/VpnInfo.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/VrmConnection.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/VrmInfo.cs (100%) rename csharp/{app => App}/RemoteSupportConsole/VrmProxy.cs (100%) create mode 100644 csharp/App/SaliMax/SaliMax.csproj rename csharp/{app => App}/SaliMax/run (BeagleBone Meiringen).sh (100%) rename csharp/{app => App}/SaliMax/src/AsciiArt.cs (100%) rename csharp/{app => App}/SaliMax/src/BusPort.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/AvgBatteriesStatus.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/Control.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/ControlRecord.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/ControlTarget.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/Controller.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/SaliMaxState.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/State.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/StateConfig.cs (100%) rename csharp/{app => App}/SaliMax/src/Controller/StatusRecord.cs (100%) rename csharp/{app => App}/SaliMax/src/Log/Ampt.cs (100%) rename csharp/{app => App}/SaliMax/src/Log/Battery48Tl.cs (100%) rename csharp/{app => App}/SaliMax/src/Log/EmuMeter.cs (100%) rename csharp/{app => App}/SaliMax/src/Log/JsonUtil.cs (100%) rename csharp/{app => App}/SaliMax/src/Log/Salimax.cs (100%) rename csharp/{app => App}/SaliMax/src/Log/TruConvertAc.cs (100%) rename csharp/{app => App}/SaliMax/src/Log/TruConvertDc.cs (100%) rename csharp/{app => App}/SaliMax/src/Program.cs (100%) rename csharp/{app => App}/SaliMax/src/S3Config.cs (100%) rename csharp/{app => App}/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs (100%) rename csharp/{app => App}/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs (100%) rename csharp/{app => App}/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs (100%) rename csharp/{app => App}/SaliMax/src/SystemConfig/Config.cs (100%) rename csharp/{app => App}/SaliMax/src/SystemConfig/Defaults.cs (100%) rename csharp/{app => App}/SaliMax/src/SystemConfig/SalimaxConfig.cs (100%) rename csharp/{app => App}/SaliMax/src/Topology.cs (100%) rename csharp/{app => App}/SaliMax/src/Utils.cs (100%) rename csharp/{app => App}/SaliMax/tunnels.html (100%) rename csharp/{app => App}/SaliMax/tunnels.sh (100%) create mode 100644 csharp/Lib/Channels/Channels.csproj rename csharp/{lib => Lib}/Channels/CloseAfter.cs (100%) rename csharp/{lib => Lib}/Channels/Connection.cs (100%) rename csharp/{lib => Lib}/Channels/Framed/Channel.cs (100%) rename csharp/{lib => Lib}/Channels/Stages/Channel.cs (100%) rename csharp/{lib => Lib}/Channels/Stages/ConnectedChannel.cs (100%) rename csharp/{lib => Lib}/Channels/Stages/Stage.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Bak/Connections/Connection.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Bak/Connections/Connections.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Bak/Connections/Extensions.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Bak/Connections/IConnection.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Bak/GenericChannel.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Bak/StreamChannel.cs (100%) rename csharp/{lib => Lib}/Channels/V2/CommandChannel.cs (100%) rename csharp/{lib => Lib}/Channels/V2/IChannel.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Pipes/AsyncPipeSource.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Pipes/AsyncPipeTarget.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Pipes/ChannelPipeSource.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Pipes/ChannelPipeTarget.cs (100%) rename csharp/{lib => Lib}/Channels/V2/Stage.cs (100%) rename csharp/{lib => Lib}/Channels/V2/StreamChannel.cs (100%) rename csharp/{lib => Lib}/Channels/V2/TcpChannel.cs (100%) rename csharp/{lib => Lib}/Devices/AMPT/Ampt.csproj (88%) rename csharp/{lib => Lib}/Devices/AMPT/AmptCommunicationUnit.cs (100%) rename csharp/{lib => Lib}/Devices/AMPT/AmptDeviceStatus.cs (100%) rename csharp/{lib => Lib}/Devices/AMPT/AmptStatus.cs (100%) rename csharp/{lib => Lib}/Devices/AMPT/AmptStringStatus.cs (100%) rename csharp/{lib => Lib}/Devices/Adam6060/Adam6060.csproj (75%) rename csharp/{lib => Lib}/Devices/Adam6060/Adam6060Control.cs (100%) rename csharp/{lib => Lib}/Devices/Adam6060/Adam6060Device.cs (100%) rename csharp/{lib => Lib}/Devices/Adam6060/Adam6060Status.cs (100%) rename csharp/{lib => Lib}/Devices/Battery48TL/Battery48TL.csproj (84%) rename csharp/{lib => Lib}/Devices/Battery48TL/Battery48TLDevice.cs (100%) rename csharp/{lib => Lib}/Devices/Battery48TL/Battery48TLStatusRecord.cs (100%) rename csharp/{lib => Lib}/Devices/Battery48TL/BatteryDataParser.cs (100%) rename csharp/{lib => Lib}/Devices/Battery48TL/Constants.cs (100%) rename csharp/{lib => Lib}/Devices/Battery48TL/LedColor.cs (100%) rename csharp/{lib => Lib}/Devices/Battery48TL/LedState.cs (100%) rename csharp/{lib => Lib}/Devices/EmuMeter/Conversions.cs (100%) rename csharp/{lib => Lib}/Devices/EmuMeter/EmuMeter.csproj (84%) rename csharp/{lib => Lib}/Devices/EmuMeter/EmuMeterDevice.cs (100%) rename csharp/{lib => Lib}/Devices/EmuMeter/EmuMeterStatus.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvert/AlarmState.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvert/MainState.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvert/Slave.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvert/SystemConfig.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvert/TruConvert.csproj (72%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvert/Utils.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/AcControlRegisters.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/AcEnums.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/AlarmMessage.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj (84%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/TruConvertAcControl.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertAc/WarningMessage.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/AlarmMessage.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/DcControlRegisters.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/DcEnums.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj (84%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/TruConvertDcControl.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/TruConvertDcDevice.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs (100%) rename csharp/{lib => Lib}/Devices/Trumpf/TruConvertDc/WarningMessage.cs (100%) rename csharp/{lib/InnovEnergy.lib.props => Lib/InnovEnergy.Lib.props} (100%) rename csharp/{lib => Lib}/Protocols/DBus/Bus.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/DBus.csproj (89%) rename csharp/{lib => Lib}/Protocols/DBus/DBusConnection.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/DBusMessageStream.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/DBusService.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/DBusDaemonApi.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/DBusDaemonConnection.Resolver.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/DBusDaemonConnection.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/MatchRule.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/ObservableDictionary.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/ReleaseNameReply.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/RequestNameOptions.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Daemon/RequestNameReply.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Env.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Interop.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Convert/StringToSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Convert/TypeToSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/ObjectPath.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Equality.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Terminals.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ArraySignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BasicTypeSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BooleanSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ByteSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/CompositeSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ContainerTypeSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DictionarySignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DoubleSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/EmptySignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/FixedTypeSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int16Signature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int32Signature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int64Signature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ObjectPathSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/SignatureTypeSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringLikeTypeSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StructSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt16Signature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt32Signature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt64Signature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/VariantSignature.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/DataTypes/Variant.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/Header/Endian.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/Header/FieldCode.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/Header/HeaderExtensions.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/Header/HeaderFlags.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/Header/MessageType.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/Message.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/Replies.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Protocol/SerialSource.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Transport/AuthenticationMethod.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Transport/BufferedSocketReader.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Transport/DBusBufferReader.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Transport/DBusBufferWriter.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Transport/DBusSocket.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Utils/DisposableStack.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Utils/Extensions.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/Utils/HexView.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/WireFormat/DBusMeasureWriter.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/WireFormat/DBusReader.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/WireFormat/DBusSocketReader.cs (100%) rename csharp/{lib => Lib}/Protocols/DBus/WireFormat/DBusWriter.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Clients/ModbusClient.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Clients/ModbusRtuClient.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Clients/ModbusTcpClient.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Connections/ModbusConnection.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Connections/ModbusSerialConnection.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Connections/ModbusTcpConnection.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/Endianness.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.Bit.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.Boolean.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.Bytes.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.Int16.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.Int32.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.Single.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.String.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.UInt16.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.UInt32.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Conversions/ModbusRegisters.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Modbus.csproj (82%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/ExceptionCode.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Exceptions.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Accessors/Accessors.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Accessors/MbAddress.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Accessors/MbBits.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Accessors/MbByte.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Accessors/MbByte{T}.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Accessors/MbWord.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Accessors/MbWords.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Commands/ReadDiscreteInputsCommandFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Commands/ReadHoldingRegistersCommandFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Commands/ReadInputRegistersCommandFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Commands/ReadWriteRegistersCommandFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Commands/WriteCoilsCommandFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Commands/WriteRegistersCommandFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Constants.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/ModbusFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Replies/ErrorResponseFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Replies/ReadDiscreteInputResponseFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Replies/ReadHoldingRegistersResponseFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Replies/ReadInputRegistersResponseFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Replies/ReadWriteRegistersCommandFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Replies/WriteCoilsResponseFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/Frames/Replies/WriteRegistersResponseFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Protocol/FunctionCode.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Tcp/MbapHeader.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Tcp/ModbusTcpFrame.cs (100%) rename csharp/{lib => Lib}/Protocols/Modbus/Util/ArraySegmentExtensions.cs (100%) rename csharp/{lib => Lib}/S3/DataRec.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Delegates/ReadRecord.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Delegates/WriteRecord.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Reader.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Reader.public.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Util/Aggregator.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Util/Sampler.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Writer.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/Internal/Writer.public.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/MemoryDriver.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/S3Config.cs (100%) rename csharp/{lib => Lib}/S3/Drivers/S3Driver.cs (100%) rename csharp/{lib => Lib}/S3/Metadata/AggregationLevel.cs (100%) rename csharp/{lib => Lib}/S3/Metadata/FieldType.cs (100%) rename csharp/{lib => Lib}/S3/Program.cs (100%) rename csharp/{lib => Lib}/S3/Records/Fields/Field.cs (100%) rename csharp/{lib => Lib}/S3/Records/Fields/NumberField.cs (100%) rename csharp/{lib => Lib}/S3/Records/Fields/TextField.cs (100%) rename csharp/{lib => Lib}/S3/Records/Fields/TextFrequency.cs (100%) rename csharp/{lib => Lib}/S3/Records/Fields/UnitAttribute.cs (100%) rename csharp/{lib => Lib}/S3/Records/Fields/WithUnit.cs (100%) rename csharp/{lib => Lib}/S3/Records/Operations/Aggregation.cs (100%) rename csharp/{lib => Lib}/S3/Records/Operations/Conversion.cs (100%) rename csharp/{lib => Lib}/S3/Records/Record.cs (100%) rename csharp/{lib => Lib}/S3/Records/Serialization/FieldTag.cs (100%) rename csharp/{lib => Lib}/S3/Records/Serialization/Parser.cs (100%) rename csharp/{lib => Lib}/S3/Records/Serialization/Serializer.cs (100%) rename csharp/{lib => Lib}/S3/Records/Specialized/AggregatedRecord.cs (100%) rename csharp/{lib => Lib}/S3/Records/Specialized/TimeStampedRecord.cs (100%) rename csharp/{lib => Lib}/S3/S3.csproj (60%) rename csharp/{lib => Lib}/S3/Serialization/JsonConverters.cs (100%) rename csharp/{lib => Lib}/StatusApi/Connections/DcConnection.cs (100%) rename csharp/{lib => Lib}/StatusApi/Connections/SinglePhaseAcConnection.cs (100%) rename csharp/{lib => Lib}/StatusApi/Connections/ThreePhaseAcConnection.cs (100%) rename csharp/{lib => Lib}/StatusApi/DeviceType.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/Battery.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/DcDcConverter.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/DcDevice.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/Device.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/GridMeter.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/IPvCoupledDevice.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/Mppt.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/SinglePhaseAcDevice.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/SinglePhaseInverter.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/SinglePhasePvInverter.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/ThreePhaseAcDevice.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/ThreePhaseInverter.cs (100%) rename csharp/{lib => Lib}/StatusApi/Devices/ThreePhasePvInverter.cs (100%) rename csharp/{lib => Lib}/StatusApi/Phases/AcPhase.cs (100%) rename csharp/{lib => Lib}/StatusApi/Phases/Phase.cs (100%) rename csharp/{lib => Lib}/StatusApi/StatusApi.csproj (75%) rename csharp/{lib => Lib}/StatusApi/Utils.cs (100%) rename csharp/{lib => Lib}/StatusData/Current.cs (100%) rename csharp/{lib => Lib}/StatusData/Json/Converters.cs (100%) rename csharp/{lib => Lib}/StatusData/Json/CurrentConverter.cs (100%) rename csharp/{lib => Lib}/StatusData/Json/PowerConverter.cs (100%) rename csharp/{lib => Lib}/StatusData/Json/ResistanceConverter.cs (100%) rename csharp/{lib => Lib}/StatusData/Json/VoltageConverter.cs (100%) rename csharp/{lib => Lib}/StatusData/Power.cs (100%) rename csharp/{lib => Lib}/StatusData/Resistance.cs (100%) rename csharp/{lib => Lib}/StatusData/State.cs (100%) rename csharp/{lib => Lib}/StatusData/StatusData.csproj (77%) rename csharp/{lib => Lib}/StatusData/Units.cs (100%) rename csharp/{lib => Lib}/StatusData/Voltage.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/RemoteCommandToProcess.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/RemotePathToRemoteCommand.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/SshHostToRemoteCommand.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/SshHostToRemotePath.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/StringToCommand.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/StringToProcess.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/StringToRemotePath.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/StringToSysPath.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/SysCommandToProcess.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/SysCommandToRemoteCommand.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/SysPathToProcess.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/SysPathToRemotePath.cs (100%) rename csharp/{lib => Lib}/SysTools/Edges/SysPathToSysCommand.cs (100%) rename csharp/{lib => Lib}/SysTools/FileIo.cs (100%) rename csharp/{lib => Lib}/SysTools/Process/AsyncProcess.cs (100%) rename csharp/{lib => Lib}/SysTools/Process/ProcessResult.cs (100%) rename csharp/{lib => Lib}/SysTools/Process/SyncProcess.cs (100%) rename csharp/{lib => Lib}/SysTools/Remote/RemoteCommand.cs (100%) rename csharp/{lib => Lib}/SysTools/Remote/RemoteFileIo.cs (100%) rename csharp/{lib => Lib}/SysTools/Remote/RemotePath.cs (100%) rename csharp/{lib => Lib}/SysTools/Remote/SshHost.cs (100%) rename csharp/{lib => Lib}/SysTools/SysCommand.cs (100%) rename csharp/{lib => Lib}/SysTools/SysDirs.cs (100%) rename csharp/{lib => Lib}/SysTools/SysPath.cs (100%) rename csharp/{lib => Lib}/SysTools/SysTools.csproj (75%) rename csharp/{lib => Lib}/SysTools/Utils/ConsoleUtils.cs (100%) rename csharp/{lib => Lib}/SysTools/Utils/EnumerableUtils.cs (100%) rename csharp/{lib => Lib}/SysTools/Utils/StringUtils.cs (100%) rename csharp/{lib => Lib}/SysTools/Utils/Utils.cs (100%) create mode 100644 csharp/Lib/Time/Time.csproj rename csharp/{lib => Lib}/Time/Unix/UnixTime.Compare.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTime.Constructors.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTime.Converters.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTime.Operators.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTime.Overrides.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTime.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTimeDelta.Compare.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTimeDelta.Constructors.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTimeDelta.Operators.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTimeDelta.Overrides.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTimeDeltaExtensions.cs (100%) rename csharp/{lib => Lib}/Time/Unix/UnixTimeSpan.cs (100%) rename csharp/{lib => Lib}/Utils/ArrayExtensions.cs (100%) rename csharp/{lib => Lib}/Utils/AsyncDelegates.cs (100%) rename csharp/{lib => Lib}/Utils/AsyncEnumerableEx.cs (100%) rename csharp/{lib => Lib}/Utils/AutoComplete.cs (100%) rename csharp/{lib => Lib}/Utils/CliCommandUtils.cs (100%) rename csharp/{lib => Lib}/Utils/ConsoleUtils.cs (100%) rename csharp/{lib => Lib}/Utils/DecimalUtils.cs (100%) rename csharp/{lib => Lib}/Utils/DictObservables.cs (100%) rename csharp/{lib => Lib}/Utils/Disposable.cs (100%) rename csharp/{lib => Lib}/Utils/EnumerableUtils.cs (100%) rename csharp/{lib => Lib}/Utils/ExceptionHandling.cs (100%) rename csharp/{lib => Lib}/Utils/FileSystem.cs (100%) rename csharp/{lib => Lib}/Utils/JsonNodeAccessors.cs (100%) rename csharp/{lib => Lib}/Utils/Maybe.cs (100%) rename csharp/{lib => Lib}/Utils/Net/NetUtils.cs (100%) rename csharp/{lib => Lib}/Utils/Net/PingExtensions.cs (100%) rename csharp/{lib => Lib}/Utils/Net/UdpExtensions.cs (100%) rename csharp/{lib => Lib}/Utils/None.cs (100%) rename csharp/{lib => Lib}/Utils/NullableUtils.cs (100%) rename csharp/{lib => Lib}/Utils/ObservableExceptionHandling.cs (100%) rename csharp/{lib => Lib}/Utils/ObservableUtils.cs (100%) rename csharp/{lib => Lib}/Utils/PointFree.cs (100%) rename csharp/{lib => Lib}/Utils/SshHost.cs (100%) rename csharp/{lib => Lib}/Utils/StreamExtensions.cs (100%) rename csharp/{lib => Lib}/Utils/StringUtils.cs (100%) rename csharp/{lib => Lib}/Utils/TaskUtils.cs (100%) rename csharp/{lib => Lib}/Utils/TextBlock.cs (100%) rename csharp/{lib => Lib}/Utils/Try/Operators.async.cs (100%) rename csharp/{lib => Lib}/Utils/Try/Operators.sync.cs (100%) rename csharp/{lib => Lib}/Utils/Try/Policy.cs (100%) rename csharp/{lib => Lib}/Utils/Try/TryAsync.async.cs (100%) rename csharp/{lib => Lib}/Utils/Try/TryAsync.cs (100%) rename csharp/{lib => Lib}/Utils/Try/TryAsync.sync.cs (100%) rename csharp/{lib => Lib}/Utils/Try/TrySync.async.cs (100%) rename csharp/{lib => Lib}/Utils/Try/TrySync.cs (100%) rename csharp/{lib => Lib}/Utils/Try/TrySync.sync.cs (100%) rename csharp/{lib => Lib}/Utils/Units.cs (100%) rename csharp/{lib => Lib}/Utils/Utils.cs (100%) rename csharp/{lib => Lib}/Utils/Utils.csproj (87%) rename csharp/{lib => Lib}/Utils/Utils.sln (100%) rename csharp/{lib => Lib}/Utils/ValueTupleUtils.cs (100%) rename csharp/{lib => Lib}/Victron/VeDBus/Program.cs (100%) rename csharp/{lib => Lib}/Victron/VeDBus/VeDBus.cs (100%) rename csharp/{lib => Lib}/Victron/VeDBus/VeDBus.csproj (88%) rename csharp/{lib => Lib}/Victron/VeDBus/VeDBusApi.cs (100%) rename csharp/{lib => Lib}/Victron/VeDBus/VeDbusService.cs (100%) rename csharp/{lib => Lib}/Victron/VeDBus/VeProperties.Dbus.cs (100%) rename csharp/{lib => Lib}/Victron/VeDBus/VeProperties.cs (100%) rename csharp/{lib => Lib}/Victron/VeDBus/VeProperty.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Detail.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Details.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Device.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/FlurlExtensions.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Installation.Settings.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Installation.Tags.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Installation.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Reply.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Requests.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/Settings.cs (100%) rename csharp/{lib => Lib}/Victron/VictronVRM/VictronVRM.csproj (92%) rename csharp/{lib => Lib}/Victron/VictronVRM/VrmAccount.cs (100%) rename csharp/{lib => Lib}/WebServer/ContentType.cs (100%) rename csharp/{lib => Lib}/WebServer/Default.cs (100%) rename csharp/{lib => Lib}/WebServer/HttpExtensions.cs (100%) rename csharp/{lib => Lib}/WebServer/HttpHeader.cs (100%) rename csharp/{lib => Lib}/WebServer/HttpMethod.cs (100%) rename csharp/{lib => Lib}/WebServer/HttpRequest.cs (100%) rename csharp/{lib => Lib}/WebServer/HttpResponse.cs (100%) rename csharp/{lib => Lib}/WebServer/WebServer.cs (100%) rename csharp/{lib => Lib}/WebServer/WebServer.csproj (76%) rename csharp/{lib => Lib}/Wireformat/WireFormat.csproj.DotSettings (100%) rename csharp/{lib => Lib}/Wireformat/build_proto.sh (100%) rename csharp/{lib => Lib}/Wireformat/package-lock.json (100%) rename csharp/{lib => Lib}/Wireformat/package.json (100%) rename csharp/{lib => Lib}/Wireformat/proto/Payload.proto (100%) rename csharp/{lib => Lib}/Wireformat/proto/VictronV1/BatteryStatus48TL.proto (100%) rename csharp/{lib => Lib}/Wireformat/proto/VictronV1/Device.proto (100%) rename csharp/{lib => Lib}/Wireformat/proto/VictronV1/VictronTopologyV1.proto (100%) delete mode 100644 csharp/app/Backend/db.sqlite delete mode 100644 csharp/app/EmuMeterDriver/EmuMeterDriver.csproj delete mode 100644 csharp/app/SaliMax/SaliMax.csproj delete mode 100644 csharp/lib/Channels/Channels.csproj delete mode 100644 csharp/lib/Time/Time.csproj diff --git a/csharp/app/Backend/Backend.csproj b/csharp/App/Backend/Backend.csproj similarity index 93% rename from csharp/app/Backend/Backend.csproj rename to csharp/App/Backend/Backend.csproj index eebe0dae8..6be32dee4 100644 --- a/csharp/app/Backend/Backend.csproj +++ b/csharp/App/Backend/Backend.csproj @@ -1,5 +1,5 @@ - + @@ -24,7 +24,7 @@ - + diff --git a/csharp/app/Backend/Controllers/Controller.cs b/csharp/App/Backend/Controllers/Controller.cs similarity index 100% rename from csharp/app/Backend/Controllers/Controller.cs rename to csharp/App/Backend/Controllers/Controller.cs diff --git a/csharp/app/Backend/Controllers/Credentials.cs b/csharp/App/Backend/Controllers/Credentials.cs similarity index 100% rename from csharp/app/Backend/Controllers/Credentials.cs rename to csharp/App/Backend/Controllers/Credentials.cs diff --git a/csharp/app/Backend/Controllers/ReturnsAttribute.cs b/csharp/App/Backend/Controllers/ReturnsAttribute.cs similarity index 100% rename from csharp/app/Backend/Controllers/ReturnsAttribute.cs rename to csharp/App/Backend/Controllers/ReturnsAttribute.cs diff --git a/csharp/app/Backend/Database/Db.cs b/csharp/App/Backend/Database/Db.cs similarity index 100% rename from csharp/app/Backend/Database/Db.cs rename to csharp/App/Backend/Database/Db.cs diff --git a/csharp/app/Backend/Database/Fake.cs b/csharp/App/Backend/Database/Fake.cs similarity index 100% rename from csharp/app/Backend/Database/Fake.cs rename to csharp/App/Backend/Database/Fake.cs diff --git a/csharp/app/Backend/Database/Folder.cs b/csharp/App/Backend/Database/Folder.cs similarity index 100% rename from csharp/app/Backend/Database/Folder.cs rename to csharp/App/Backend/Database/Folder.cs diff --git a/csharp/app/Backend/Database/Installation.cs b/csharp/App/Backend/Database/Installation.cs similarity index 100% rename from csharp/app/Backend/Database/Installation.cs rename to csharp/App/Backend/Database/Installation.cs diff --git a/csharp/app/Backend/Database/User.cs b/csharp/App/Backend/Database/User.cs similarity index 100% rename from csharp/app/Backend/Database/User.cs rename to csharp/App/Backend/Database/User.cs diff --git a/csharp/app/Backend/Database/User2Folder.cs b/csharp/App/Backend/Database/User2Folder.cs similarity index 100% rename from csharp/app/Backend/Database/User2Folder.cs rename to csharp/App/Backend/Database/User2Folder.cs diff --git a/csharp/app/Backend/Database/User2Installation.cs b/csharp/App/Backend/Database/User2Installation.cs similarity index 100% rename from csharp/app/Backend/Database/User2Installation.cs rename to csharp/App/Backend/Database/User2Installation.cs diff --git a/csharp/app/Backend/FakeFolders.csv b/csharp/App/Backend/FakeFolders.csv similarity index 100% rename from csharp/app/Backend/FakeFolders.csv rename to csharp/App/Backend/FakeFolders.csv diff --git a/csharp/app/Backend/FakeInstallations.csv b/csharp/App/Backend/FakeInstallations.csv similarity index 100% rename from csharp/app/Backend/FakeInstallations.csv rename to csharp/App/Backend/FakeInstallations.csv diff --git a/csharp/app/Backend/FakePasswords.csv b/csharp/App/Backend/FakePasswords.csv similarity index 100% rename from csharp/app/Backend/FakePasswords.csv rename to csharp/App/Backend/FakePasswords.csv diff --git a/csharp/app/Backend/FakeUsers.csv b/csharp/App/Backend/FakeUsers.csv similarity index 100% rename from csharp/app/Backend/FakeUsers.csv rename to csharp/App/Backend/FakeUsers.csv diff --git a/csharp/app/Backend/HeaderFilter.cs b/csharp/App/Backend/HeaderFilter.cs similarity index 100% rename from csharp/app/Backend/HeaderFilter.cs rename to csharp/App/Backend/HeaderFilter.cs diff --git a/csharp/app/Backend/Model/Folder.cs b/csharp/App/Backend/Model/Folder.cs similarity index 100% rename from csharp/app/Backend/Model/Folder.cs rename to csharp/App/Backend/Model/Folder.cs diff --git a/csharp/app/Backend/Model/Installation.cs b/csharp/App/Backend/Model/Installation.cs similarity index 100% rename from csharp/app/Backend/Model/Installation.cs rename to csharp/App/Backend/Model/Installation.cs diff --git a/csharp/app/Backend/Model/Relations/Relation.cs b/csharp/App/Backend/Model/Relations/Relation.cs similarity index 100% rename from csharp/app/Backend/Model/Relations/Relation.cs rename to csharp/App/Backend/Model/Relations/Relation.cs diff --git a/csharp/app/Backend/Model/Relations/Session.cs b/csharp/App/Backend/Model/Relations/Session.cs similarity index 100% rename from csharp/app/Backend/Model/Relations/Session.cs rename to csharp/App/Backend/Model/Relations/Session.cs diff --git a/csharp/app/Backend/Model/Relations/User2Folder.cs b/csharp/App/Backend/Model/Relations/User2Folder.cs similarity index 100% rename from csharp/app/Backend/Model/Relations/User2Folder.cs rename to csharp/App/Backend/Model/Relations/User2Folder.cs diff --git a/csharp/app/Backend/Model/Relations/User2Installation.cs b/csharp/App/Backend/Model/Relations/User2Installation.cs similarity index 100% rename from csharp/app/Backend/Model/Relations/User2Installation.cs rename to csharp/App/Backend/Model/Relations/User2Installation.cs diff --git a/csharp/app/Backend/Model/TreeNode.Equality.cs b/csharp/App/Backend/Model/TreeNode.Equality.cs similarity index 100% rename from csharp/app/Backend/Model/TreeNode.Equality.cs rename to csharp/App/Backend/Model/TreeNode.Equality.cs diff --git a/csharp/app/Backend/Model/TreeNode.cs b/csharp/App/Backend/Model/TreeNode.cs similarity index 100% rename from csharp/app/Backend/Model/TreeNode.cs rename to csharp/App/Backend/Model/TreeNode.cs diff --git a/csharp/app/Backend/Model/User.cs b/csharp/App/Backend/Model/User.cs similarity index 100% rename from csharp/app/Backend/Model/User.cs rename to csharp/App/Backend/Model/User.cs diff --git a/csharp/app/Backend/Program.cs b/csharp/App/Backend/Program.cs similarity index 100% rename from csharp/app/Backend/Program.cs rename to csharp/App/Backend/Program.cs diff --git a/csharp/app/Backend/Properties/launchSettings.json b/csharp/App/Backend/Properties/launchSettings.json similarity index 100% rename from csharp/app/Backend/Properties/launchSettings.json rename to csharp/App/Backend/Properties/launchSettings.json diff --git a/csharp/app/Backend/Utils/Crypto.cs b/csharp/App/Backend/Utils/Crypto.cs similarity index 100% rename from csharp/app/Backend/Utils/Crypto.cs rename to csharp/App/Backend/Utils/Crypto.cs diff --git a/csharp/app/Backend/Utils/Result.cs b/csharp/App/Backend/Utils/Result.cs similarity index 100% rename from csharp/app/Backend/Utils/Result.cs rename to csharp/App/Backend/Utils/Result.cs diff --git a/csharp/App/Backend/db.sqlite b/csharp/App/Backend/db.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..982a3ab9194e88a44231a09570b7baa0be6f249f GIT binary patch literal 290816 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 - + @@ -7,7 +7,7 @@ - + diff --git a/csharp/app/BmsTunnel/CliPrograms.cs b/csharp/App/BmsTunnel/CliPrograms.cs similarity index 100% rename from csharp/app/BmsTunnel/CliPrograms.cs rename to csharp/App/BmsTunnel/CliPrograms.cs diff --git a/csharp/app/BmsTunnel/Program.cs b/csharp/App/BmsTunnel/Program.cs similarity index 100% rename from csharp/app/BmsTunnel/Program.cs rename to csharp/App/BmsTunnel/Program.cs diff --git a/csharp/app/BmsTunnel/debug.sh b/csharp/App/BmsTunnel/debug.sh similarity index 100% rename from csharp/app/BmsTunnel/debug.sh rename to csharp/App/BmsTunnel/debug.sh diff --git a/csharp/app/BmsTunnel/parameters.txt b/csharp/App/BmsTunnel/parameters.txt similarity index 100% rename from csharp/app/BmsTunnel/parameters.txt rename to csharp/App/BmsTunnel/parameters.txt diff --git a/csharp/app/Collector/Collector.csproj b/csharp/App/Collector/Collector.csproj similarity index 52% rename from csharp/app/Collector/Collector.csproj rename to csharp/App/Collector/Collector.csproj index b2e28418b..27b560c8d 100644 --- a/csharp/app/Collector/Collector.csproj +++ b/csharp/App/Collector/Collector.csproj @@ -1,9 +1,9 @@ - + - - + + diff --git a/csharp/app/Collector/Collector.sln b/csharp/App/Collector/Collector.sln similarity index 100% rename from csharp/app/Collector/Collector.sln rename to csharp/App/Collector/Collector.sln diff --git a/csharp/app/Collector/src/BatteryDataParser.cs b/csharp/App/Collector/src/BatteryDataParser.cs similarity index 100% rename from csharp/app/Collector/src/BatteryDataParser.cs rename to csharp/App/Collector/src/BatteryDataParser.cs diff --git a/csharp/app/Collector/src/BatteryDataParserV4.cs b/csharp/App/Collector/src/BatteryDataParserV4.cs similarity index 100% rename from csharp/app/Collector/src/BatteryDataParserV4.cs rename to csharp/App/Collector/src/BatteryDataParserV4.cs diff --git a/csharp/app/Collector/src/Influx/FieldAttribute.cs b/csharp/App/Collector/src/Influx/FieldAttribute.cs similarity index 100% rename from csharp/app/Collector/src/Influx/FieldAttribute.cs rename to csharp/App/Collector/src/Influx/FieldAttribute.cs diff --git a/csharp/app/Collector/src/Influx/InfluxRecord.cs b/csharp/App/Collector/src/Influx/InfluxRecord.cs similarity index 100% rename from csharp/app/Collector/src/Influx/InfluxRecord.cs rename to csharp/App/Collector/src/Influx/InfluxRecord.cs diff --git a/csharp/app/Collector/src/Influx/LineProtocolSyntax.cs b/csharp/App/Collector/src/Influx/LineProtocolSyntax.cs similarity index 100% rename from csharp/app/Collector/src/Influx/LineProtocolSyntax.cs rename to csharp/App/Collector/src/Influx/LineProtocolSyntax.cs diff --git a/csharp/app/Collector/src/Influx/TagAttribute.cs b/csharp/App/Collector/src/Influx/TagAttribute.cs similarity index 100% rename from csharp/app/Collector/src/Influx/TagAttribute.cs rename to csharp/App/Collector/src/Influx/TagAttribute.cs diff --git a/csharp/app/Collector/src/Program.cs b/csharp/App/Collector/src/Program.cs similarity index 100% rename from csharp/app/Collector/src/Program.cs rename to csharp/App/Collector/src/Program.cs diff --git a/csharp/app/Collector/src/Records/Alarms.cs b/csharp/App/Collector/src/Records/Alarms.cs similarity index 100% rename from csharp/app/Collector/src/Records/Alarms.cs rename to csharp/App/Collector/src/Records/Alarms.cs diff --git a/csharp/app/Collector/src/Records/BatteryRecord.cs b/csharp/App/Collector/src/Records/BatteryRecord.cs similarity index 100% rename from csharp/app/Collector/src/Records/BatteryRecord.cs rename to csharp/App/Collector/src/Records/BatteryRecord.cs diff --git a/csharp/app/Collector/src/Records/BatteryStatus.cs b/csharp/App/Collector/src/Records/BatteryStatus.cs similarity index 100% rename from csharp/app/Collector/src/Records/BatteryStatus.cs rename to csharp/App/Collector/src/Records/BatteryStatus.cs diff --git a/csharp/app/Collector/src/Records/Error.cs b/csharp/App/Collector/src/Records/Error.cs similarity index 100% rename from csharp/app/Collector/src/Records/Error.cs rename to csharp/App/Collector/src/Records/Error.cs diff --git a/csharp/app/Collector/src/Records/InstallationStatus.cs b/csharp/App/Collector/src/Records/InstallationStatus.cs similarity index 100% rename from csharp/app/Collector/src/Records/InstallationStatus.cs rename to csharp/App/Collector/src/Records/InstallationStatus.cs diff --git a/csharp/app/Collector/src/Records/IoStatus.cs b/csharp/App/Collector/src/Records/IoStatus.cs similarity index 100% rename from csharp/app/Collector/src/Records/IoStatus.cs rename to csharp/App/Collector/src/Records/IoStatus.cs diff --git a/csharp/app/Collector/src/Records/Leds.cs b/csharp/App/Collector/src/Records/Leds.cs similarity index 100% rename from csharp/app/Collector/src/Records/Leds.cs rename to csharp/App/Collector/src/Records/Leds.cs diff --git a/csharp/app/Collector/src/Records/Temperatures.cs b/csharp/App/Collector/src/Records/Temperatures.cs similarity index 100% rename from csharp/app/Collector/src/Records/Temperatures.cs rename to csharp/App/Collector/src/Records/Temperatures.cs diff --git a/csharp/app/Collector/src/Records/Warnings.cs b/csharp/App/Collector/src/Records/Warnings.cs similarity index 100% rename from csharp/app/Collector/src/Records/Warnings.cs rename to csharp/App/Collector/src/Records/Warnings.cs diff --git a/csharp/app/Collector/src/Settings.cs b/csharp/App/Collector/src/Settings.cs similarity index 100% rename from csharp/app/Collector/src/Settings.cs rename to csharp/App/Collector/src/Settings.cs diff --git a/csharp/app/Collector/src/Utils/Extensions.cs b/csharp/App/Collector/src/Utils/Extensions.cs similarity index 100% rename from csharp/app/Collector/src/Utils/Extensions.cs rename to csharp/App/Collector/src/Utils/Extensions.cs diff --git a/csharp/app/Collector/src/Utils/Log.cs b/csharp/App/Collector/src/Utils/Log.cs similarity index 100% rename from csharp/app/Collector/src/Utils/Log.cs rename to csharp/App/Collector/src/Utils/Log.cs diff --git a/csharp/app/Collector/src/Utils/Property.cs b/csharp/App/Collector/src/Utils/Property.cs similarity index 100% rename from csharp/app/Collector/src/Utils/Property.cs rename to csharp/App/Collector/src/Utils/Property.cs diff --git a/csharp/app/Collector/src/Utils/ReadOnlyListExtensions.cs b/csharp/App/Collector/src/Utils/ReadOnlyListExtensions.cs similarity index 100% rename from csharp/app/Collector/src/Utils/ReadOnlyListExtensions.cs rename to csharp/App/Collector/src/Utils/ReadOnlyListExtensions.cs diff --git a/csharp/app/Collector/src/Utils/Utils.cs b/csharp/App/Collector/src/Utils/Utils.cs similarity index 100% rename from csharp/app/Collector/src/Utils/Utils.cs rename to csharp/App/Collector/src/Utils/Utils.cs diff --git a/csharp/app/EmuMeterDriver/Config.cs b/csharp/App/EmuMeterDriver/Config.cs similarity index 100% rename from csharp/app/EmuMeterDriver/Config.cs rename to csharp/App/EmuMeterDriver/Config.cs diff --git a/csharp/app/EmuMeterDriver/EmuMeterDriver.cs b/csharp/App/EmuMeterDriver/EmuMeterDriver.cs similarity index 100% rename from csharp/app/EmuMeterDriver/EmuMeterDriver.cs rename to csharp/App/EmuMeterDriver/EmuMeterDriver.cs diff --git a/csharp/App/EmuMeterDriver/EmuMeterDriver.csproj b/csharp/App/EmuMeterDriver/EmuMeterDriver.csproj new file mode 100644 index 000000000..b2f8696ed --- /dev/null +++ b/csharp/App/EmuMeterDriver/EmuMeterDriver.csproj @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/csharp/app/EmuMeterDriver/Nic.cs b/csharp/App/EmuMeterDriver/Nic.cs similarity index 100% rename from csharp/app/EmuMeterDriver/Nic.cs rename to csharp/App/EmuMeterDriver/Nic.cs diff --git a/csharp/app/EmuMeterDriver/Program.cs b/csharp/App/EmuMeterDriver/Program.cs similarity index 100% rename from csharp/app/EmuMeterDriver/Program.cs rename to csharp/App/EmuMeterDriver/Program.cs diff --git a/csharp/app/EmuMeterDriver/Signal.cs b/csharp/App/EmuMeterDriver/Signal.cs similarity index 100% rename from csharp/app/EmuMeterDriver/Signal.cs rename to csharp/App/EmuMeterDriver/Signal.cs diff --git a/csharp/app/EmuMeterDriver/Utils.cs b/csharp/App/EmuMeterDriver/Utils.cs similarity index 100% rename from csharp/app/EmuMeterDriver/Utils.cs rename to csharp/App/EmuMeterDriver/Utils.cs diff --git a/csharp/app/EmuMeterDriver/debug.sh b/csharp/App/EmuMeterDriver/debug.sh similarity index 100% rename from csharp/app/EmuMeterDriver/debug.sh rename to csharp/App/EmuMeterDriver/debug.sh diff --git a/csharp/app/EmuMeterDriver/service/log/run b/csharp/App/EmuMeterDriver/service/log/run similarity index 100% rename from csharp/app/EmuMeterDriver/service/log/run rename to csharp/App/EmuMeterDriver/service/log/run diff --git a/csharp/app/EmuMeterDriver/service/run b/csharp/App/EmuMeterDriver/service/run similarity index 100% rename from csharp/app/EmuMeterDriver/service/run rename to csharp/App/EmuMeterDriver/service/run diff --git a/csharp/app/InnovEnergy.app.props b/csharp/App/InnovEnergy.App.props similarity index 100% rename from csharp/app/InnovEnergy.app.props rename to csharp/App/InnovEnergy.App.props diff --git a/csharp/app/OpenVpnCertificatesServer/Files.cs b/csharp/App/OpenVpnCertificatesServer/Files.cs similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/Files.cs rename to csharp/App/OpenVpnCertificatesServer/Files.cs diff --git a/csharp/app/OpenVpnCertificatesServer/Http.cs b/csharp/App/OpenVpnCertificatesServer/Http.cs similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/Http.cs rename to csharp/App/OpenVpnCertificatesServer/Http.cs diff --git a/csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj b/csharp/App/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj similarity index 58% rename from csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj rename to csharp/App/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj index 2773cd430..e44b0a11e 100644 --- a/csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj +++ b/csharp/App/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj @@ -1,5 +1,5 @@ - + @@ -8,8 +8,9 @@ - - + + + diff --git a/csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.sln b/csharp/App/OpenVpnCertificatesServer/OpenVpnCertificatesServer.sln similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.sln rename to csharp/App/OpenVpnCertificatesServer/OpenVpnCertificatesServer.sln diff --git a/csharp/app/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs b/csharp/App/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs rename to csharp/App/OpenVpnCertificatesServer/PKI/CertificateAuthority.cs diff --git a/csharp/app/OpenVpnCertificatesServer/PKI/Pem.cs b/csharp/App/OpenVpnCertificatesServer/PKI/Pem.cs similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/PKI/Pem.cs rename to csharp/App/OpenVpnCertificatesServer/PKI/Pem.cs diff --git a/csharp/app/OpenVpnCertificatesServer/PKI/PwdFinder.cs b/csharp/App/OpenVpnCertificatesServer/PKI/PwdFinder.cs similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/PKI/PwdFinder.cs rename to csharp/App/OpenVpnCertificatesServer/PKI/PwdFinder.cs diff --git a/csharp/app/OpenVpnCertificatesServer/Program.cs b/csharp/App/OpenVpnCertificatesServer/Program.cs similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/Program.cs rename to csharp/App/OpenVpnCertificatesServer/Program.cs diff --git a/csharp/app/OpenVpnCertificatesServer/Utils.cs b/csharp/App/OpenVpnCertificatesServer/Utils.cs similarity index 100% rename from csharp/app/OpenVpnCertificatesServer/Utils.cs rename to csharp/App/OpenVpnCertificatesServer/Utils.cs diff --git a/csharp/app/RemoteSupportConsole/Login.cs b/csharp/App/RemoteSupportConsole/Login.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/Login.cs rename to csharp/App/RemoteSupportConsole/Login.cs diff --git a/csharp/app/RemoteSupportConsole/ObservablePipeSource.cs b/csharp/App/RemoteSupportConsole/ObservablePipeSource.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/ObservablePipeSource.cs rename to csharp/App/RemoteSupportConsole/ObservablePipeSource.cs diff --git a/csharp/app/RemoteSupportConsole/Program.cs b/csharp/App/RemoteSupportConsole/Program.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/Program.cs rename to csharp/App/RemoteSupportConsole/Program.cs diff --git a/csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj b/csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj similarity index 67% rename from csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj rename to csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj index cb8c7d1b8..c00eed4bb 100644 --- a/csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj +++ b/csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj @@ -1,9 +1,9 @@ - + - - + + diff --git a/csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj.DotSettings b/csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj.DotSettings similarity index 100% rename from csharp/app/RemoteSupportConsole/RemoteSupportConsole.csproj.DotSettings rename to csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj.DotSettings diff --git a/csharp/app/RemoteSupportConsole/Ssh.cs b/csharp/App/RemoteSupportConsole/Ssh.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/Ssh.cs rename to csharp/App/RemoteSupportConsole/Ssh.cs diff --git a/csharp/app/RemoteSupportConsole/VpnConnection.cs b/csharp/App/RemoteSupportConsole/VpnConnection.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/VpnConnection.cs rename to csharp/App/RemoteSupportConsole/VpnConnection.cs diff --git a/csharp/app/RemoteSupportConsole/VpnInfo.cs b/csharp/App/RemoteSupportConsole/VpnInfo.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/VpnInfo.cs rename to csharp/App/RemoteSupportConsole/VpnInfo.cs diff --git a/csharp/app/RemoteSupportConsole/VrmConnection.cs b/csharp/App/RemoteSupportConsole/VrmConnection.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/VrmConnection.cs rename to csharp/App/RemoteSupportConsole/VrmConnection.cs diff --git a/csharp/app/RemoteSupportConsole/VrmInfo.cs b/csharp/App/RemoteSupportConsole/VrmInfo.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/VrmInfo.cs rename to csharp/App/RemoteSupportConsole/VrmInfo.cs diff --git a/csharp/app/RemoteSupportConsole/VrmProxy.cs b/csharp/App/RemoteSupportConsole/VrmProxy.cs similarity index 100% rename from csharp/app/RemoteSupportConsole/VrmProxy.cs rename to csharp/App/RemoteSupportConsole/VrmProxy.cs diff --git a/csharp/App/SaliMax/SaliMax.csproj b/csharp/App/SaliMax/SaliMax.csproj new file mode 100644 index 000000000..c647ee0d5 --- /dev/null +++ b/csharp/App/SaliMax/SaliMax.csproj @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/csharp/app/SaliMax/run (BeagleBone Meiringen).sh b/csharp/App/SaliMax/run (BeagleBone Meiringen).sh similarity index 100% rename from csharp/app/SaliMax/run (BeagleBone Meiringen).sh rename to csharp/App/SaliMax/run (BeagleBone Meiringen).sh diff --git a/csharp/app/SaliMax/src/AsciiArt.cs b/csharp/App/SaliMax/src/AsciiArt.cs similarity index 100% rename from csharp/app/SaliMax/src/AsciiArt.cs rename to csharp/App/SaliMax/src/AsciiArt.cs diff --git a/csharp/app/SaliMax/src/BusPort.cs b/csharp/App/SaliMax/src/BusPort.cs similarity index 100% rename from csharp/app/SaliMax/src/BusPort.cs rename to csharp/App/SaliMax/src/BusPort.cs diff --git a/csharp/app/SaliMax/src/Controller/AvgBatteriesStatus.cs b/csharp/App/SaliMax/src/Controller/AvgBatteriesStatus.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/AvgBatteriesStatus.cs rename to csharp/App/SaliMax/src/Controller/AvgBatteriesStatus.cs diff --git a/csharp/app/SaliMax/src/Controller/Control.cs b/csharp/App/SaliMax/src/Controller/Control.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/Control.cs rename to csharp/App/SaliMax/src/Controller/Control.cs diff --git a/csharp/app/SaliMax/src/Controller/ControlRecord.cs b/csharp/App/SaliMax/src/Controller/ControlRecord.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/ControlRecord.cs rename to csharp/App/SaliMax/src/Controller/ControlRecord.cs diff --git a/csharp/app/SaliMax/src/Controller/ControlTarget.cs b/csharp/App/SaliMax/src/Controller/ControlTarget.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/ControlTarget.cs rename to csharp/App/SaliMax/src/Controller/ControlTarget.cs diff --git a/csharp/app/SaliMax/src/Controller/Controller.cs b/csharp/App/SaliMax/src/Controller/Controller.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/Controller.cs rename to csharp/App/SaliMax/src/Controller/Controller.cs diff --git a/csharp/app/SaliMax/src/Controller/SaliMaxState.cs b/csharp/App/SaliMax/src/Controller/SaliMaxState.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/SaliMaxState.cs rename to csharp/App/SaliMax/src/Controller/SaliMaxState.cs diff --git a/csharp/app/SaliMax/src/Controller/State.cs b/csharp/App/SaliMax/src/Controller/State.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/State.cs rename to csharp/App/SaliMax/src/Controller/State.cs diff --git a/csharp/app/SaliMax/src/Controller/StateConfig.cs b/csharp/App/SaliMax/src/Controller/StateConfig.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/StateConfig.cs rename to csharp/App/SaliMax/src/Controller/StateConfig.cs diff --git a/csharp/app/SaliMax/src/Controller/StatusRecord.cs b/csharp/App/SaliMax/src/Controller/StatusRecord.cs similarity index 100% rename from csharp/app/SaliMax/src/Controller/StatusRecord.cs rename to csharp/App/SaliMax/src/Controller/StatusRecord.cs diff --git a/csharp/app/SaliMax/src/Log/Ampt.cs b/csharp/App/SaliMax/src/Log/Ampt.cs similarity index 100% rename from csharp/app/SaliMax/src/Log/Ampt.cs rename to csharp/App/SaliMax/src/Log/Ampt.cs diff --git a/csharp/app/SaliMax/src/Log/Battery48Tl.cs b/csharp/App/SaliMax/src/Log/Battery48Tl.cs similarity index 100% rename from csharp/app/SaliMax/src/Log/Battery48Tl.cs rename to csharp/App/SaliMax/src/Log/Battery48Tl.cs diff --git a/csharp/app/SaliMax/src/Log/EmuMeter.cs b/csharp/App/SaliMax/src/Log/EmuMeter.cs similarity index 100% rename from csharp/app/SaliMax/src/Log/EmuMeter.cs rename to csharp/App/SaliMax/src/Log/EmuMeter.cs diff --git a/csharp/app/SaliMax/src/Log/JsonUtil.cs b/csharp/App/SaliMax/src/Log/JsonUtil.cs similarity index 100% rename from csharp/app/SaliMax/src/Log/JsonUtil.cs rename to csharp/App/SaliMax/src/Log/JsonUtil.cs diff --git a/csharp/app/SaliMax/src/Log/Salimax.cs b/csharp/App/SaliMax/src/Log/Salimax.cs similarity index 100% rename from csharp/app/SaliMax/src/Log/Salimax.cs rename to csharp/App/SaliMax/src/Log/Salimax.cs diff --git a/csharp/app/SaliMax/src/Log/TruConvertAc.cs b/csharp/App/SaliMax/src/Log/TruConvertAc.cs similarity index 100% rename from csharp/app/SaliMax/src/Log/TruConvertAc.cs rename to csharp/App/SaliMax/src/Log/TruConvertAc.cs diff --git a/csharp/app/SaliMax/src/Log/TruConvertDc.cs b/csharp/App/SaliMax/src/Log/TruConvertDc.cs similarity index 100% rename from csharp/app/SaliMax/src/Log/TruConvertDc.cs rename to csharp/App/SaliMax/src/Log/TruConvertDc.cs diff --git a/csharp/app/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs similarity index 100% rename from csharp/app/SaliMax/src/Program.cs rename to csharp/App/SaliMax/src/Program.cs diff --git a/csharp/app/SaliMax/src/S3Config.cs b/csharp/App/SaliMax/src/S3Config.cs similarity index 100% rename from csharp/app/SaliMax/src/S3Config.cs rename to csharp/App/SaliMax/src/S3Config.cs diff --git a/csharp/app/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs b/csharp/App/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs similarity index 100% rename from csharp/app/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs rename to csharp/App/SaliMax/src/SaliMaxRelays/RelayMapBoolean.cs diff --git a/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs b/csharp/App/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs similarity index 100% rename from csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs rename to csharp/App/SaliMax/src/SaliMaxRelays/SaliMaxRelaysDevice.cs diff --git a/csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs b/csharp/App/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs similarity index 100% rename from csharp/app/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs rename to csharp/App/SaliMax/src/SaliMaxRelays/SaliMaxRelaysStatus.cs diff --git a/csharp/app/SaliMax/src/SystemConfig/Config.cs b/csharp/App/SaliMax/src/SystemConfig/Config.cs similarity index 100% rename from csharp/app/SaliMax/src/SystemConfig/Config.cs rename to csharp/App/SaliMax/src/SystemConfig/Config.cs diff --git a/csharp/app/SaliMax/src/SystemConfig/Defaults.cs b/csharp/App/SaliMax/src/SystemConfig/Defaults.cs similarity index 100% rename from csharp/app/SaliMax/src/SystemConfig/Defaults.cs rename to csharp/App/SaliMax/src/SystemConfig/Defaults.cs diff --git a/csharp/app/SaliMax/src/SystemConfig/SalimaxConfig.cs b/csharp/App/SaliMax/src/SystemConfig/SalimaxConfig.cs similarity index 100% rename from csharp/app/SaliMax/src/SystemConfig/SalimaxConfig.cs rename to csharp/App/SaliMax/src/SystemConfig/SalimaxConfig.cs diff --git a/csharp/app/SaliMax/src/Topology.cs b/csharp/App/SaliMax/src/Topology.cs similarity index 100% rename from csharp/app/SaliMax/src/Topology.cs rename to csharp/App/SaliMax/src/Topology.cs diff --git a/csharp/app/SaliMax/src/Utils.cs b/csharp/App/SaliMax/src/Utils.cs similarity index 100% rename from csharp/app/SaliMax/src/Utils.cs rename to csharp/App/SaliMax/src/Utils.cs diff --git a/csharp/app/SaliMax/tunnels.html b/csharp/App/SaliMax/tunnels.html similarity index 100% rename from csharp/app/SaliMax/tunnels.html rename to csharp/App/SaliMax/tunnels.html diff --git a/csharp/app/SaliMax/tunnels.sh b/csharp/App/SaliMax/tunnels.sh similarity index 100% rename from csharp/app/SaliMax/tunnels.sh rename to csharp/App/SaliMax/tunnels.sh diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 5002df0a2..70c4b2f57 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -1,32 +1,32 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Collector", "app/Collector/Collector.csproj", "{E3A5F3A3-72A5-47CC-85C6-2D8E962A0EC1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Collector", "App/Collector/Collector.csproj", "{E3A5F3A3-72A5-47CC-85C6-2D8E962A0EC1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenVpnCertificatesServer", "app/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj", "{CF4834CB-91B7-4172-AC13-ECDA8613CD17}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenVpnCertificatesServer", "App/OpenVpnCertificatesServer/OpenVpnCertificatesServer.csproj", "{CF4834CB-91B7-4172-AC13-ECDA8613CD17}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoteSupportConsole", "app/RemoteSupportConsole/RemoteSupportConsole.csproj", "{B1268C03-66EB-4486-8BFC-B439225D9D54}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoteSupportConsole", "App/RemoteSupportConsole/RemoteSupportConsole.csproj", "{B1268C03-66EB-4486-8BFC-B439225D9D54}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SysTools", "lib/SysTools/SysTools.csproj", "{4A67D79F-F0C9-4BBC-9601-D5948E6C05D3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SysTools", "Lib/SysTools/SysTools.csproj", "{4A67D79F-F0C9-4BBC-9601-D5948E6C05D3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebServer", "lib/WebServer/WebServer.csproj", "{B2627B9F-41DF-44F7-A0D1-CA71FF4A007A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebServer", "Lib/WebServer/WebServer.csproj", "{B2627B9F-41DF-44F7-A0D1-CA71FF4A007A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Time", "lib/Time/Time.csproj", "{442A8366-C177-48FE-84A7-BDF6470A09FF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Time", "Lib/Time/Time.csproj", "{442A8366-C177-48FE-84A7-BDF6470A09FF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeterDriver", "app/EmuMeterDriver/EmuMeterDriver.csproj", "{F65F33B0-3522-4008-8D1E-47EF8E4C7AC7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeterDriver", "App/EmuMeterDriver/EmuMeterDriver.csproj", "{F65F33B0-3522-4008-8D1E-47EF8E4C7AC7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BmsTunnel", "app/BmsTunnel/BmsTunnel.csproj", "{40B45363-BE34-420B-8F87-775EE6EE3513}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BmsTunnel", "App/BmsTunnel/BmsTunnel.csproj", "{40B45363-BE34-420B-8F87-775EE6EE3513}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{145597B4-3E30-45E6-9F72-4DD43194539A}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{145597B4-3E30-45E6-9F72-4DD43194539A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3", "lib/S3/S3.csproj", "{C3639841-13F4-4F24-99C6-7D965593BF89}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3", "Lib/S3/S3.csproj", "{C3639841-13F4-4F24-99C6-7D965593BF89}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deprecated", "deprecated", "{46DE03C4-52D1-47AA-8E60-8BB15361D723}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaliMax", "app/SaliMax/SaliMax.csproj", "{25073794-D859-4824-9984-194C7E928496}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaliMax", "App/SaliMax/SaliMax.csproj", "{25073794-D859-4824-9984-194C7E928496}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusApi", "lib/StatusApi/StatusApi.csproj", "{9D17E78C-8A70-43DB-A619-DC12D20D023D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusApi", "Lib/StatusApi/StatusApi.csproj", "{9D17E78C-8A70-43DB-A619-DC12D20D023D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Devices", "Devices", "{4931A385-24DC-4E78-BFF4-356F8D6D5183}" EndProject @@ -36,36 +36,36 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Victron", "Victron", "{BD8C EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Trumpf", "Trumpf", "{DDDBEFD0-5DEA-4C7C-A9F2-FDB4636CF092}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvert", "lib/Devices/Trumpf/TruConvert/TruConvert.csproj", "{EF46CF7B-823E-4CB7-966F-EDDC144C7954}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvert", "Lib/Devices/Trumpf/TruConvert/TruConvert.csproj", "{EF46CF7B-823E-4CB7-966F-EDDC144C7954}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertAc", "lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj", "{1F4B445E-459E-44CD-813E-6D725EBB81E8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertAc", "Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj", "{1F4B445E-459E-44CD-813E-6D725EBB81E8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertDc", "lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj", "{F6F29829-C31A-4994-A698-E441BEA631C6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TruConvertDc", "Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj", "{F6F29829-C31A-4994-A698-E441BEA631C6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DBus", "lib/Protocols/DBus/DBus.csproj", "{8C3C620A-087D-4DD6-B493-A47FC643F8DC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DBus", "Lib/Protocols/DBus/DBus.csproj", "{8C3C620A-087D-4DD6-B493-A47FC643F8DC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus", "lib/Protocols/Modbus/Modbus.csproj", "{E4AE6A33-0DEB-48EB-9D57-C0C7C63FC267}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus", "Lib/Protocols/Modbus/Modbus.csproj", "{E4AE6A33-0DEB-48EB-9D57-C0C7C63FC267}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VeDBus", "lib/Victron/VeDBus/VeDBus.csproj", "{50B26E29-1B99-4D07-BCA5-359CD550BBAA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VeDBus", "Lib/Victron/VeDBus/VeDBus.csproj", "{50B26E29-1B99-4D07-BCA5-359CD550BBAA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VictronVRM", "lib/Victron/VictronVRM/VictronVRM.csproj", "{FE05DF69-B5C7-4C2E-8FB9-7776441A7622}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VictronVRM", "Lib/Victron/VictronVRM/VictronVRM.csproj", "{FE05DF69-B5C7-4C2E-8FB9-7776441A7622}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ampt", "lib/Devices/AMPT/Ampt.csproj", "{77AF3A64-2878-4150-BCD0-F16530783165}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ampt", "Lib/Devices/AMPT/Ampt.csproj", "{77AF3A64-2878-4150-BCD0-F16530783165}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Battery48TL", "lib/Devices/Battery48TL/Battery48TL.csproj", "{1C3F443A-B339-4B08-80E6-8A84817FFEC9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Battery48TL", "Lib/Devices/Battery48TL/Battery48TL.csproj", "{1C3F443A-B339-4B08-80E6-8A84817FFEC9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeter", "lib/Devices/EmuMeter/EmuMeter.csproj", "{152A4168-F612-493C-BBEA-8EB26E6E2D34}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmuMeter", "Lib/Devices/EmuMeter/EmuMeter.csproj", "{152A4168-F612-493C-BBEA-8EB26E6E2D34}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "lib/Utils/Utils.csproj", "{89A3E29C-4E57-47FE-A800-12AC68418264}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "Lib/Utils/Utils.csproj", "{89A3E29C-4E57-47FE-A800-12AC68418264}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adam6060", "lib/Devices/Adam6060/Adam6060.csproj", "{4AFDB799-E6A4-4DCA-8B6D-8C0F98398461}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Adam6060", "Lib/Devices/Adam6060/Adam6060.csproj", "{4AFDB799-E6A4-4DCA-8B6D-8C0F98398461}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Channels", "lib/Channels/Channels.csproj", "{AF7E8DCA-8D48-498E-AB3D-208061B244DC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Channels", "Lib/Channels/Channels.csproj", "{AF7E8DCA-8D48-498E-AB3D-208061B244DC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "app/Backend/Backend.csproj", "{A56F58C2-B265-435B-A985-53B4D6F49B1A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "App/Backend/Backend.csproj", "{A56F58C2-B265-435B-A985-53B4D6F49B1A}" EndProject EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusData", "lib\StatusData\StatusData.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusData", "Lib\StatusData\StatusData.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" EndProject Global diff --git a/csharp/Lib/Channels/Channels.csproj b/csharp/Lib/Channels/Channels.csproj new file mode 100644 index 000000000..9eb898d4e --- /dev/null +++ b/csharp/Lib/Channels/Channels.csproj @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/csharp/lib/Channels/CloseAfter.cs b/csharp/Lib/Channels/CloseAfter.cs similarity index 100% rename from csharp/lib/Channels/CloseAfter.cs rename to csharp/Lib/Channels/CloseAfter.cs diff --git a/csharp/lib/Channels/Connection.cs b/csharp/Lib/Channels/Connection.cs similarity index 100% rename from csharp/lib/Channels/Connection.cs rename to csharp/Lib/Channels/Connection.cs diff --git a/csharp/lib/Channels/Framed/Channel.cs b/csharp/Lib/Channels/Framed/Channel.cs similarity index 100% rename from csharp/lib/Channels/Framed/Channel.cs rename to csharp/Lib/Channels/Framed/Channel.cs diff --git a/csharp/lib/Channels/Stages/Channel.cs b/csharp/Lib/Channels/Stages/Channel.cs similarity index 100% rename from csharp/lib/Channels/Stages/Channel.cs rename to csharp/Lib/Channels/Stages/Channel.cs diff --git a/csharp/lib/Channels/Stages/ConnectedChannel.cs b/csharp/Lib/Channels/Stages/ConnectedChannel.cs similarity index 100% rename from csharp/lib/Channels/Stages/ConnectedChannel.cs rename to csharp/Lib/Channels/Stages/ConnectedChannel.cs diff --git a/csharp/lib/Channels/Stages/Stage.cs b/csharp/Lib/Channels/Stages/Stage.cs similarity index 100% rename from csharp/lib/Channels/Stages/Stage.cs rename to csharp/Lib/Channels/Stages/Stage.cs diff --git a/csharp/lib/Channels/V2/Bak/Connections/Connection.cs b/csharp/Lib/Channels/V2/Bak/Connections/Connection.cs similarity index 100% rename from csharp/lib/Channels/V2/Bak/Connections/Connection.cs rename to csharp/Lib/Channels/V2/Bak/Connections/Connection.cs diff --git a/csharp/lib/Channels/V2/Bak/Connections/Connections.cs b/csharp/Lib/Channels/V2/Bak/Connections/Connections.cs similarity index 100% rename from csharp/lib/Channels/V2/Bak/Connections/Connections.cs rename to csharp/Lib/Channels/V2/Bak/Connections/Connections.cs diff --git a/csharp/lib/Channels/V2/Bak/Connections/Extensions.cs b/csharp/Lib/Channels/V2/Bak/Connections/Extensions.cs similarity index 100% rename from csharp/lib/Channels/V2/Bak/Connections/Extensions.cs rename to csharp/Lib/Channels/V2/Bak/Connections/Extensions.cs diff --git a/csharp/lib/Channels/V2/Bak/Connections/IConnection.cs b/csharp/Lib/Channels/V2/Bak/Connections/IConnection.cs similarity index 100% rename from csharp/lib/Channels/V2/Bak/Connections/IConnection.cs rename to csharp/Lib/Channels/V2/Bak/Connections/IConnection.cs diff --git a/csharp/lib/Channels/V2/Bak/GenericChannel.cs b/csharp/Lib/Channels/V2/Bak/GenericChannel.cs similarity index 100% rename from csharp/lib/Channels/V2/Bak/GenericChannel.cs rename to csharp/Lib/Channels/V2/Bak/GenericChannel.cs diff --git a/csharp/lib/Channels/V2/Bak/StreamChannel.cs b/csharp/Lib/Channels/V2/Bak/StreamChannel.cs similarity index 100% rename from csharp/lib/Channels/V2/Bak/StreamChannel.cs rename to csharp/Lib/Channels/V2/Bak/StreamChannel.cs diff --git a/csharp/lib/Channels/V2/CommandChannel.cs b/csharp/Lib/Channels/V2/CommandChannel.cs similarity index 100% rename from csharp/lib/Channels/V2/CommandChannel.cs rename to csharp/Lib/Channels/V2/CommandChannel.cs diff --git a/csharp/lib/Channels/V2/IChannel.cs b/csharp/Lib/Channels/V2/IChannel.cs similarity index 100% rename from csharp/lib/Channels/V2/IChannel.cs rename to csharp/Lib/Channels/V2/IChannel.cs diff --git a/csharp/lib/Channels/V2/Pipes/AsyncPipeSource.cs b/csharp/Lib/Channels/V2/Pipes/AsyncPipeSource.cs similarity index 100% rename from csharp/lib/Channels/V2/Pipes/AsyncPipeSource.cs rename to csharp/Lib/Channels/V2/Pipes/AsyncPipeSource.cs diff --git a/csharp/lib/Channels/V2/Pipes/AsyncPipeTarget.cs b/csharp/Lib/Channels/V2/Pipes/AsyncPipeTarget.cs similarity index 100% rename from csharp/lib/Channels/V2/Pipes/AsyncPipeTarget.cs rename to csharp/Lib/Channels/V2/Pipes/AsyncPipeTarget.cs diff --git a/csharp/lib/Channels/V2/Pipes/ChannelPipeSource.cs b/csharp/Lib/Channels/V2/Pipes/ChannelPipeSource.cs similarity index 100% rename from csharp/lib/Channels/V2/Pipes/ChannelPipeSource.cs rename to csharp/Lib/Channels/V2/Pipes/ChannelPipeSource.cs diff --git a/csharp/lib/Channels/V2/Pipes/ChannelPipeTarget.cs b/csharp/Lib/Channels/V2/Pipes/ChannelPipeTarget.cs similarity index 100% rename from csharp/lib/Channels/V2/Pipes/ChannelPipeTarget.cs rename to csharp/Lib/Channels/V2/Pipes/ChannelPipeTarget.cs diff --git a/csharp/lib/Channels/V2/Stage.cs b/csharp/Lib/Channels/V2/Stage.cs similarity index 100% rename from csharp/lib/Channels/V2/Stage.cs rename to csharp/Lib/Channels/V2/Stage.cs diff --git a/csharp/lib/Channels/V2/StreamChannel.cs b/csharp/Lib/Channels/V2/StreamChannel.cs similarity index 100% rename from csharp/lib/Channels/V2/StreamChannel.cs rename to csharp/Lib/Channels/V2/StreamChannel.cs diff --git a/csharp/lib/Channels/V2/TcpChannel.cs b/csharp/Lib/Channels/V2/TcpChannel.cs similarity index 100% rename from csharp/lib/Channels/V2/TcpChannel.cs rename to csharp/Lib/Channels/V2/TcpChannel.cs diff --git a/csharp/lib/Devices/AMPT/Ampt.csproj b/csharp/Lib/Devices/AMPT/Ampt.csproj similarity index 88% rename from csharp/lib/Devices/AMPT/Ampt.csproj rename to csharp/Lib/Devices/AMPT/Ampt.csproj index 2190a3c06..ea8cbf21c 100644 --- a/csharp/lib/Devices/AMPT/Ampt.csproj +++ b/csharp/Lib/Devices/AMPT/Ampt.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Devices/AMPT/AmptCommunicationUnit.cs b/csharp/Lib/Devices/AMPT/AmptCommunicationUnit.cs similarity index 100% rename from csharp/lib/Devices/AMPT/AmptCommunicationUnit.cs rename to csharp/Lib/Devices/AMPT/AmptCommunicationUnit.cs diff --git a/csharp/lib/Devices/AMPT/AmptDeviceStatus.cs b/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs similarity index 100% rename from csharp/lib/Devices/AMPT/AmptDeviceStatus.cs rename to csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs diff --git a/csharp/lib/Devices/AMPT/AmptStatus.cs b/csharp/Lib/Devices/AMPT/AmptStatus.cs similarity index 100% rename from csharp/lib/Devices/AMPT/AmptStatus.cs rename to csharp/Lib/Devices/AMPT/AmptStatus.cs diff --git a/csharp/lib/Devices/AMPT/AmptStringStatus.cs b/csharp/Lib/Devices/AMPT/AmptStringStatus.cs similarity index 100% rename from csharp/lib/Devices/AMPT/AmptStringStatus.cs rename to csharp/Lib/Devices/AMPT/AmptStringStatus.cs diff --git a/csharp/lib/Devices/Adam6060/Adam6060.csproj b/csharp/Lib/Devices/Adam6060/Adam6060.csproj similarity index 75% rename from csharp/lib/Devices/Adam6060/Adam6060.csproj rename to csharp/Lib/Devices/Adam6060/Adam6060.csproj index de99fbbaa..1a36e43e1 100644 --- a/csharp/lib/Devices/Adam6060/Adam6060.csproj +++ b/csharp/Lib/Devices/Adam6060/Adam6060.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Devices/Adam6060/Adam6060Control.cs b/csharp/Lib/Devices/Adam6060/Adam6060Control.cs similarity index 100% rename from csharp/lib/Devices/Adam6060/Adam6060Control.cs rename to csharp/Lib/Devices/Adam6060/Adam6060Control.cs diff --git a/csharp/lib/Devices/Adam6060/Adam6060Device.cs b/csharp/Lib/Devices/Adam6060/Adam6060Device.cs similarity index 100% rename from csharp/lib/Devices/Adam6060/Adam6060Device.cs rename to csharp/Lib/Devices/Adam6060/Adam6060Device.cs diff --git a/csharp/lib/Devices/Adam6060/Adam6060Status.cs b/csharp/Lib/Devices/Adam6060/Adam6060Status.cs similarity index 100% rename from csharp/lib/Devices/Adam6060/Adam6060Status.cs rename to csharp/Lib/Devices/Adam6060/Adam6060Status.cs diff --git a/csharp/lib/Devices/Battery48TL/Battery48TL.csproj b/csharp/Lib/Devices/Battery48TL/Battery48TL.csproj similarity index 84% rename from csharp/lib/Devices/Battery48TL/Battery48TL.csproj rename to csharp/Lib/Devices/Battery48TL/Battery48TL.csproj index bbfe44b02..ce3b83de6 100644 --- a/csharp/lib/Devices/Battery48TL/Battery48TL.csproj +++ b/csharp/Lib/Devices/Battery48TL/Battery48TL.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Devices/Battery48TL/Battery48TLDevice.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs similarity index 100% rename from csharp/lib/Devices/Battery48TL/Battery48TLDevice.cs rename to csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs diff --git a/csharp/lib/Devices/Battery48TL/Battery48TLStatusRecord.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs similarity index 100% rename from csharp/lib/Devices/Battery48TL/Battery48TLStatusRecord.cs rename to csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs diff --git a/csharp/lib/Devices/Battery48TL/BatteryDataParser.cs b/csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs similarity index 100% rename from csharp/lib/Devices/Battery48TL/BatteryDataParser.cs rename to csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs diff --git a/csharp/lib/Devices/Battery48TL/Constants.cs b/csharp/Lib/Devices/Battery48TL/Constants.cs similarity index 100% rename from csharp/lib/Devices/Battery48TL/Constants.cs rename to csharp/Lib/Devices/Battery48TL/Constants.cs diff --git a/csharp/lib/Devices/Battery48TL/LedColor.cs b/csharp/Lib/Devices/Battery48TL/LedColor.cs similarity index 100% rename from csharp/lib/Devices/Battery48TL/LedColor.cs rename to csharp/Lib/Devices/Battery48TL/LedColor.cs diff --git a/csharp/lib/Devices/Battery48TL/LedState.cs b/csharp/Lib/Devices/Battery48TL/LedState.cs similarity index 100% rename from csharp/lib/Devices/Battery48TL/LedState.cs rename to csharp/Lib/Devices/Battery48TL/LedState.cs diff --git a/csharp/lib/Devices/EmuMeter/Conversions.cs b/csharp/Lib/Devices/EmuMeter/Conversions.cs similarity index 100% rename from csharp/lib/Devices/EmuMeter/Conversions.cs rename to csharp/Lib/Devices/EmuMeter/Conversions.cs diff --git a/csharp/lib/Devices/EmuMeter/EmuMeter.csproj b/csharp/Lib/Devices/EmuMeter/EmuMeter.csproj similarity index 84% rename from csharp/lib/Devices/EmuMeter/EmuMeter.csproj rename to csharp/Lib/Devices/EmuMeter/EmuMeter.csproj index bbfe44b02..ce3b83de6 100644 --- a/csharp/lib/Devices/EmuMeter/EmuMeter.csproj +++ b/csharp/Lib/Devices/EmuMeter/EmuMeter.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Devices/EmuMeter/EmuMeterDevice.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs similarity index 100% rename from csharp/lib/Devices/EmuMeter/EmuMeterDevice.cs rename to csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs diff --git a/csharp/lib/Devices/EmuMeter/EmuMeterStatus.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs similarity index 100% rename from csharp/lib/Devices/EmuMeter/EmuMeterStatus.cs rename to csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvert/AlarmState.cs b/csharp/Lib/Devices/Trumpf/TruConvert/AlarmState.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvert/AlarmState.cs rename to csharp/Lib/Devices/Trumpf/TruConvert/AlarmState.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvert/MainState.cs b/csharp/Lib/Devices/Trumpf/TruConvert/MainState.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvert/MainState.cs rename to csharp/Lib/Devices/Trumpf/TruConvert/MainState.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvert/Slave.cs b/csharp/Lib/Devices/Trumpf/TruConvert/Slave.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvert/Slave.cs rename to csharp/Lib/Devices/Trumpf/TruConvert/Slave.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvert/SystemConfig.cs b/csharp/Lib/Devices/Trumpf/TruConvert/SystemConfig.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvert/SystemConfig.cs rename to csharp/Lib/Devices/Trumpf/TruConvert/SystemConfig.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj b/csharp/Lib/Devices/Trumpf/TruConvert/TruConvert.csproj similarity index 72% rename from csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj rename to csharp/Lib/Devices/Trumpf/TruConvert/TruConvert.csproj index 660a234b8..ca3eb7a2a 100644 --- a/csharp/lib/Devices/Trumpf/TruConvert/TruConvert.csproj +++ b/csharp/Lib/Devices/Trumpf/TruConvert/TruConvert.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Devices/Trumpf/TruConvert/Utils.cs b/csharp/Lib/Devices/Trumpf/TruConvert/Utils.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvert/Utils.cs rename to csharp/Lib/Devices/Trumpf/TruConvert/Utils.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/AcControlRegisters.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/AcControlRegisters.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertAc/AcControlRegisters.cs rename to csharp/Lib/Devices/Trumpf/TruConvertAc/AcControlRegisters.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/AcEnums.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/AcEnums.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertAc/AcEnums.cs rename to csharp/Lib/Devices/Trumpf/TruConvertAc/AcEnums.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs rename to csharp/Lib/Devices/Trumpf/TruConvertAc/AlarmMessage.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj similarity index 84% rename from csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj rename to csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj index b29f9d3f8..3a70b12a0 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj +++ b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAc.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAcControl.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcControl.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAcControl.cs rename to csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcControl.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs rename to csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs rename to csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs rename to csharp/Lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/AlarmMessage.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/AlarmMessage.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertDc/AlarmMessage.cs rename to csharp/Lib/Devices/Trumpf/TruConvertDc/AlarmMessage.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/DcControlRegisters.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/DcControlRegisters.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertDc/DcControlRegisters.cs rename to csharp/Lib/Devices/Trumpf/TruConvertDc/DcControlRegisters.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/DcEnums.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/DcEnums.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertDc/DcEnums.cs rename to csharp/Lib/Devices/Trumpf/TruConvertDc/DcEnums.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj b/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj similarity index 84% rename from csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj rename to csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj index 8f13140f6..1628a2b19 100644 --- a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj +++ b/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDc.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDcControl.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcControl.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDcControl.cs rename to csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcControl.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDcDevice.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcDevice.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDcDevice.cs rename to csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcDevice.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs rename to csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs diff --git a/csharp/lib/Devices/Trumpf/TruConvertDc/WarningMessage.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/WarningMessage.cs similarity index 100% rename from csharp/lib/Devices/Trumpf/TruConvertDc/WarningMessage.cs rename to csharp/Lib/Devices/Trumpf/TruConvertDc/WarningMessage.cs diff --git a/csharp/lib/InnovEnergy.lib.props b/csharp/Lib/InnovEnergy.Lib.props similarity index 100% rename from csharp/lib/InnovEnergy.lib.props rename to csharp/Lib/InnovEnergy.Lib.props diff --git a/csharp/lib/Protocols/DBus/Bus.cs b/csharp/Lib/Protocols/DBus/Bus.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Bus.cs rename to csharp/Lib/Protocols/DBus/Bus.cs diff --git a/csharp/lib/Protocols/DBus/DBus.csproj b/csharp/Lib/Protocols/DBus/DBus.csproj similarity index 89% rename from csharp/lib/Protocols/DBus/DBus.csproj rename to csharp/Lib/Protocols/DBus/DBus.csproj index e33bdceca..01a9e0400 100644 --- a/csharp/lib/Protocols/DBus/DBus.csproj +++ b/csharp/Lib/Protocols/DBus/DBus.csproj @@ -1,5 +1,5 @@ - + DBus Library diff --git a/csharp/lib/Protocols/DBus/DBusConnection.cs b/csharp/Lib/Protocols/DBus/DBusConnection.cs similarity index 100% rename from csharp/lib/Protocols/DBus/DBusConnection.cs rename to csharp/Lib/Protocols/DBus/DBusConnection.cs diff --git a/csharp/lib/Protocols/DBus/DBusMessageStream.cs b/csharp/Lib/Protocols/DBus/DBusMessageStream.cs similarity index 100% rename from csharp/lib/Protocols/DBus/DBusMessageStream.cs rename to csharp/Lib/Protocols/DBus/DBusMessageStream.cs diff --git a/csharp/lib/Protocols/DBus/DBusService.cs b/csharp/Lib/Protocols/DBus/DBusService.cs similarity index 100% rename from csharp/lib/Protocols/DBus/DBusService.cs rename to csharp/Lib/Protocols/DBus/DBusService.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/DBusDaemonApi.cs b/csharp/Lib/Protocols/DBus/Daemon/DBusDaemonApi.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/DBusDaemonApi.cs rename to csharp/Lib/Protocols/DBus/Daemon/DBusDaemonApi.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/DBusDaemonConnection.Resolver.cs b/csharp/Lib/Protocols/DBus/Daemon/DBusDaemonConnection.Resolver.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/DBusDaemonConnection.Resolver.cs rename to csharp/Lib/Protocols/DBus/Daemon/DBusDaemonConnection.Resolver.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/DBusDaemonConnection.cs b/csharp/Lib/Protocols/DBus/Daemon/DBusDaemonConnection.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/DBusDaemonConnection.cs rename to csharp/Lib/Protocols/DBus/Daemon/DBusDaemonConnection.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/MatchRule.cs b/csharp/Lib/Protocols/DBus/Daemon/MatchRule.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/MatchRule.cs rename to csharp/Lib/Protocols/DBus/Daemon/MatchRule.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/ObservableDictionary.cs b/csharp/Lib/Protocols/DBus/Daemon/ObservableDictionary.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/ObservableDictionary.cs rename to csharp/Lib/Protocols/DBus/Daemon/ObservableDictionary.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/ReleaseNameReply.cs b/csharp/Lib/Protocols/DBus/Daemon/ReleaseNameReply.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/ReleaseNameReply.cs rename to csharp/Lib/Protocols/DBus/Daemon/ReleaseNameReply.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/RequestNameOptions.cs b/csharp/Lib/Protocols/DBus/Daemon/RequestNameOptions.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/RequestNameOptions.cs rename to csharp/Lib/Protocols/DBus/Daemon/RequestNameOptions.cs diff --git a/csharp/lib/Protocols/DBus/Daemon/RequestNameReply.cs b/csharp/Lib/Protocols/DBus/Daemon/RequestNameReply.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Daemon/RequestNameReply.cs rename to csharp/Lib/Protocols/DBus/Daemon/RequestNameReply.cs diff --git a/csharp/lib/Protocols/DBus/Env.cs b/csharp/Lib/Protocols/DBus/Env.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Env.cs rename to csharp/Lib/Protocols/DBus/Env.cs diff --git a/csharp/lib/Protocols/DBus/Interop.cs b/csharp/Lib/Protocols/DBus/Interop.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Interop.cs rename to csharp/Lib/Protocols/DBus/Interop.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Convert/StringToSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Convert/StringToSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Convert/StringToSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Convert/StringToSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Convert/TypeToSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Convert/TypeToSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Convert/TypeToSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Convert/TypeToSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/ObjectPath.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/ObjectPath.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/ObjectPath.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/ObjectPath.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Equality.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Equality.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Equality.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Equality.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Terminals.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Terminals.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Terminals.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.Terminals.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Signature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ArraySignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ArraySignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ArraySignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ArraySignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BasicTypeSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BasicTypeSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BasicTypeSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BasicTypeSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BooleanSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BooleanSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BooleanSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/BooleanSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ByteSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ByteSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ByteSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ByteSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/CompositeSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/CompositeSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/CompositeSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/CompositeSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ContainerTypeSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ContainerTypeSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ContainerTypeSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ContainerTypeSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DictionarySignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DictionarySignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DictionarySignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DictionarySignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DoubleSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DoubleSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DoubleSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/DoubleSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/EmptySignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/EmptySignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/EmptySignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/EmptySignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/FixedTypeSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/FixedTypeSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/FixedTypeSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/FixedTypeSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int16Signature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int16Signature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int16Signature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int16Signature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int32Signature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int32Signature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int32Signature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int32Signature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int64Signature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int64Signature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int64Signature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/Int64Signature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ObjectPathSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ObjectPathSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ObjectPathSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/ObjectPathSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/SignatureTypeSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/SignatureTypeSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/SignatureTypeSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/SignatureTypeSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringLikeTypeSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringLikeTypeSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringLikeTypeSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringLikeTypeSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StringSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StructSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StructSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StructSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/StructSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt16Signature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt16Signature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt16Signature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt16Signature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt32Signature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt32Signature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt32Signature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt32Signature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt64Signature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt64Signature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt64Signature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/UInt64Signature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/VariantSignature.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/VariantSignature.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/VariantSignature.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Signatures/Specialized/VariantSignature.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/DataTypes/Variant.cs b/csharp/Lib/Protocols/DBus/Protocol/DataTypes/Variant.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/DataTypes/Variant.cs rename to csharp/Lib/Protocols/DBus/Protocol/DataTypes/Variant.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/Header/Endian.cs b/csharp/Lib/Protocols/DBus/Protocol/Header/Endian.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/Header/Endian.cs rename to csharp/Lib/Protocols/DBus/Protocol/Header/Endian.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/Header/FieldCode.cs b/csharp/Lib/Protocols/DBus/Protocol/Header/FieldCode.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/Header/FieldCode.cs rename to csharp/Lib/Protocols/DBus/Protocol/Header/FieldCode.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/Header/HeaderExtensions.cs b/csharp/Lib/Protocols/DBus/Protocol/Header/HeaderExtensions.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/Header/HeaderExtensions.cs rename to csharp/Lib/Protocols/DBus/Protocol/Header/HeaderExtensions.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/Header/HeaderFlags.cs b/csharp/Lib/Protocols/DBus/Protocol/Header/HeaderFlags.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/Header/HeaderFlags.cs rename to csharp/Lib/Protocols/DBus/Protocol/Header/HeaderFlags.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/Header/MessageType.cs b/csharp/Lib/Protocols/DBus/Protocol/Header/MessageType.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/Header/MessageType.cs rename to csharp/Lib/Protocols/DBus/Protocol/Header/MessageType.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/Message.cs b/csharp/Lib/Protocols/DBus/Protocol/Message.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/Message.cs rename to csharp/Lib/Protocols/DBus/Protocol/Message.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/Replies.cs b/csharp/Lib/Protocols/DBus/Protocol/Replies.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/Replies.cs rename to csharp/Lib/Protocols/DBus/Protocol/Replies.cs diff --git a/csharp/lib/Protocols/DBus/Protocol/SerialSource.cs b/csharp/Lib/Protocols/DBus/Protocol/SerialSource.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Protocol/SerialSource.cs rename to csharp/Lib/Protocols/DBus/Protocol/SerialSource.cs diff --git a/csharp/lib/Protocols/DBus/Transport/AuthenticationMethod.cs b/csharp/Lib/Protocols/DBus/Transport/AuthenticationMethod.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Transport/AuthenticationMethod.cs rename to csharp/Lib/Protocols/DBus/Transport/AuthenticationMethod.cs diff --git a/csharp/lib/Protocols/DBus/Transport/BufferedSocketReader.cs b/csharp/Lib/Protocols/DBus/Transport/BufferedSocketReader.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Transport/BufferedSocketReader.cs rename to csharp/Lib/Protocols/DBus/Transport/BufferedSocketReader.cs diff --git a/csharp/lib/Protocols/DBus/Transport/DBusBufferReader.cs b/csharp/Lib/Protocols/DBus/Transport/DBusBufferReader.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Transport/DBusBufferReader.cs rename to csharp/Lib/Protocols/DBus/Transport/DBusBufferReader.cs diff --git a/csharp/lib/Protocols/DBus/Transport/DBusBufferWriter.cs b/csharp/Lib/Protocols/DBus/Transport/DBusBufferWriter.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Transport/DBusBufferWriter.cs rename to csharp/Lib/Protocols/DBus/Transport/DBusBufferWriter.cs diff --git a/csharp/lib/Protocols/DBus/Transport/DBusSocket.cs b/csharp/Lib/Protocols/DBus/Transport/DBusSocket.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Transport/DBusSocket.cs rename to csharp/Lib/Protocols/DBus/Transport/DBusSocket.cs diff --git a/csharp/lib/Protocols/DBus/Utils/DisposableStack.cs b/csharp/Lib/Protocols/DBus/Utils/DisposableStack.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Utils/DisposableStack.cs rename to csharp/Lib/Protocols/DBus/Utils/DisposableStack.cs diff --git a/csharp/lib/Protocols/DBus/Utils/Extensions.cs b/csharp/Lib/Protocols/DBus/Utils/Extensions.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Utils/Extensions.cs rename to csharp/Lib/Protocols/DBus/Utils/Extensions.cs diff --git a/csharp/lib/Protocols/DBus/Utils/HexView.cs b/csharp/Lib/Protocols/DBus/Utils/HexView.cs similarity index 100% rename from csharp/lib/Protocols/DBus/Utils/HexView.cs rename to csharp/Lib/Protocols/DBus/Utils/HexView.cs diff --git a/csharp/lib/Protocols/DBus/WireFormat/DBusMeasureWriter.cs b/csharp/Lib/Protocols/DBus/WireFormat/DBusMeasureWriter.cs similarity index 100% rename from csharp/lib/Protocols/DBus/WireFormat/DBusMeasureWriter.cs rename to csharp/Lib/Protocols/DBus/WireFormat/DBusMeasureWriter.cs diff --git a/csharp/lib/Protocols/DBus/WireFormat/DBusReader.cs b/csharp/Lib/Protocols/DBus/WireFormat/DBusReader.cs similarity index 100% rename from csharp/lib/Protocols/DBus/WireFormat/DBusReader.cs rename to csharp/Lib/Protocols/DBus/WireFormat/DBusReader.cs diff --git a/csharp/lib/Protocols/DBus/WireFormat/DBusSocketReader.cs b/csharp/Lib/Protocols/DBus/WireFormat/DBusSocketReader.cs similarity index 100% rename from csharp/lib/Protocols/DBus/WireFormat/DBusSocketReader.cs rename to csharp/Lib/Protocols/DBus/WireFormat/DBusSocketReader.cs diff --git a/csharp/lib/Protocols/DBus/WireFormat/DBusWriter.cs b/csharp/Lib/Protocols/DBus/WireFormat/DBusWriter.cs similarity index 100% rename from csharp/lib/Protocols/DBus/WireFormat/DBusWriter.cs rename to csharp/Lib/Protocols/DBus/WireFormat/DBusWriter.cs diff --git a/csharp/lib/Protocols/Modbus/Clients/ModbusClient.cs b/csharp/Lib/Protocols/Modbus/Clients/ModbusClient.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Clients/ModbusClient.cs rename to csharp/Lib/Protocols/Modbus/Clients/ModbusClient.cs diff --git a/csharp/lib/Protocols/Modbus/Clients/ModbusRtuClient.cs b/csharp/Lib/Protocols/Modbus/Clients/ModbusRtuClient.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Clients/ModbusRtuClient.cs rename to csharp/Lib/Protocols/Modbus/Clients/ModbusRtuClient.cs diff --git a/csharp/lib/Protocols/Modbus/Clients/ModbusTcpClient.cs b/csharp/Lib/Protocols/Modbus/Clients/ModbusTcpClient.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Clients/ModbusTcpClient.cs rename to csharp/Lib/Protocols/Modbus/Clients/ModbusTcpClient.cs diff --git a/csharp/lib/Protocols/Modbus/Connections/ModbusConnection.cs b/csharp/Lib/Protocols/Modbus/Connections/ModbusConnection.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Connections/ModbusConnection.cs rename to csharp/Lib/Protocols/Modbus/Connections/ModbusConnection.cs diff --git a/csharp/lib/Protocols/Modbus/Connections/ModbusSerialConnection.cs b/csharp/Lib/Protocols/Modbus/Connections/ModbusSerialConnection.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Connections/ModbusSerialConnection.cs rename to csharp/Lib/Protocols/Modbus/Connections/ModbusSerialConnection.cs diff --git a/csharp/lib/Protocols/Modbus/Connections/ModbusTcpConnection.cs b/csharp/Lib/Protocols/Modbus/Connections/ModbusTcpConnection.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Connections/ModbusTcpConnection.cs rename to csharp/Lib/Protocols/Modbus/Connections/ModbusTcpConnection.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/Endianness.cs b/csharp/Lib/Protocols/Modbus/Conversions/Endianness.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/Endianness.cs rename to csharp/Lib/Protocols/Modbus/Conversions/Endianness.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Bit.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Bit.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Bit.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Bit.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Boolean.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Boolean.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Boolean.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Boolean.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Bytes.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Bytes.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Bytes.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Bytes.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Int16.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Int16.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Int16.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Int16.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Int32.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Int32.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Int32.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Int32.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Single.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Single.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.Single.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.Single.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.String.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.String.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.String.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.String.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt16.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt16.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt16.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt16.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt32.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt32.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt32.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.UInt32.cs diff --git a/csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.cs b/csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Conversions/ModbusRegisters.cs rename to csharp/Lib/Protocols/Modbus/Conversions/ModbusRegisters.cs diff --git a/csharp/lib/Protocols/Modbus/Modbus.csproj b/csharp/Lib/Protocols/Modbus/Modbus.csproj similarity index 82% rename from csharp/lib/Protocols/Modbus/Modbus.csproj rename to csharp/Lib/Protocols/Modbus/Modbus.csproj index d40e6dc28..460195f09 100644 --- a/csharp/lib/Protocols/Modbus/Modbus.csproj +++ b/csharp/Lib/Protocols/Modbus/Modbus.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Protocols/Modbus/Protocol/ExceptionCode.cs b/csharp/Lib/Protocols/Modbus/Protocol/ExceptionCode.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/ExceptionCode.cs rename to csharp/Lib/Protocols/Modbus/Protocol/ExceptionCode.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Exceptions.cs b/csharp/Lib/Protocols/Modbus/Protocol/Exceptions.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Exceptions.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Exceptions.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/Accessors.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/Accessors.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/Accessors.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/Accessors.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbAddress.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbAddress.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbAddress.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbAddress.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbBits.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbBits.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbBits.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbBits.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte{T}.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte{T}.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte{T}.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbByte{T}.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWord.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWord.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWord.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWord.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWords.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWords.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWords.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Accessors/MbWords.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadDiscreteInputsCommandFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadDiscreteInputsCommandFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadDiscreteInputsCommandFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadDiscreteInputsCommandFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadHoldingRegistersCommandFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadHoldingRegistersCommandFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadHoldingRegistersCommandFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadHoldingRegistersCommandFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadInputRegistersCommandFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadInputRegistersCommandFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadInputRegistersCommandFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadInputRegistersCommandFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadWriteRegistersCommandFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadWriteRegistersCommandFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/ReadWriteRegistersCommandFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/ReadWriteRegistersCommandFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/WriteCoilsCommandFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/WriteCoilsCommandFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/WriteCoilsCommandFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/WriteCoilsCommandFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/WriteRegistersCommandFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/WriteRegistersCommandFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Commands/WriteRegistersCommandFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Commands/WriteRegistersCommandFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Constants.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Constants.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Constants.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Constants.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/ModbusFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/ModbusFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/ModbusFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/ModbusFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ErrorResponseFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ErrorResponseFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ErrorResponseFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ErrorResponseFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadDiscreteInputResponseFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadDiscreteInputResponseFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadDiscreteInputResponseFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadDiscreteInputResponseFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadHoldingRegistersResponseFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadHoldingRegistersResponseFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadHoldingRegistersResponseFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadHoldingRegistersResponseFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadInputRegistersResponseFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadInputRegistersResponseFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadInputRegistersResponseFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadInputRegistersResponseFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadWriteRegistersCommandFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadWriteRegistersCommandFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/ReadWriteRegistersCommandFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/ReadWriteRegistersCommandFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/WriteCoilsResponseFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/WriteCoilsResponseFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/WriteCoilsResponseFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/WriteCoilsResponseFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/WriteRegistersResponseFrame.cs b/csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/WriteRegistersResponseFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/Frames/Replies/WriteRegistersResponseFrame.cs rename to csharp/Lib/Protocols/Modbus/Protocol/Frames/Replies/WriteRegistersResponseFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Protocol/FunctionCode.cs b/csharp/Lib/Protocols/Modbus/Protocol/FunctionCode.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Protocol/FunctionCode.cs rename to csharp/Lib/Protocols/Modbus/Protocol/FunctionCode.cs diff --git a/csharp/lib/Protocols/Modbus/Tcp/MbapHeader.cs b/csharp/Lib/Protocols/Modbus/Tcp/MbapHeader.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Tcp/MbapHeader.cs rename to csharp/Lib/Protocols/Modbus/Tcp/MbapHeader.cs diff --git a/csharp/lib/Protocols/Modbus/Tcp/ModbusTcpFrame.cs b/csharp/Lib/Protocols/Modbus/Tcp/ModbusTcpFrame.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Tcp/ModbusTcpFrame.cs rename to csharp/Lib/Protocols/Modbus/Tcp/ModbusTcpFrame.cs diff --git a/csharp/lib/Protocols/Modbus/Util/ArraySegmentExtensions.cs b/csharp/Lib/Protocols/Modbus/Util/ArraySegmentExtensions.cs similarity index 100% rename from csharp/lib/Protocols/Modbus/Util/ArraySegmentExtensions.cs rename to csharp/Lib/Protocols/Modbus/Util/ArraySegmentExtensions.cs diff --git a/csharp/lib/S3/DataRec.cs b/csharp/Lib/S3/DataRec.cs similarity index 100% rename from csharp/lib/S3/DataRec.cs rename to csharp/Lib/S3/DataRec.cs diff --git a/csharp/lib/S3/Drivers/Internal/Delegates/ReadRecord.cs b/csharp/Lib/S3/Drivers/Internal/Delegates/ReadRecord.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Delegates/ReadRecord.cs rename to csharp/Lib/S3/Drivers/Internal/Delegates/ReadRecord.cs diff --git a/csharp/lib/S3/Drivers/Internal/Delegates/WriteRecord.cs b/csharp/Lib/S3/Drivers/Internal/Delegates/WriteRecord.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Delegates/WriteRecord.cs rename to csharp/Lib/S3/Drivers/Internal/Delegates/WriteRecord.cs diff --git a/csharp/lib/S3/Drivers/Internal/Reader.cs b/csharp/Lib/S3/Drivers/Internal/Reader.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Reader.cs rename to csharp/Lib/S3/Drivers/Internal/Reader.cs diff --git a/csharp/lib/S3/Drivers/Internal/Reader.public.cs b/csharp/Lib/S3/Drivers/Internal/Reader.public.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Reader.public.cs rename to csharp/Lib/S3/Drivers/Internal/Reader.public.cs diff --git a/csharp/lib/S3/Drivers/Internal/Util/Aggregator.cs b/csharp/Lib/S3/Drivers/Internal/Util/Aggregator.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Util/Aggregator.cs rename to csharp/Lib/S3/Drivers/Internal/Util/Aggregator.cs diff --git a/csharp/lib/S3/Drivers/Internal/Util/Sampler.cs b/csharp/Lib/S3/Drivers/Internal/Util/Sampler.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Util/Sampler.cs rename to csharp/Lib/S3/Drivers/Internal/Util/Sampler.cs diff --git a/csharp/lib/S3/Drivers/Internal/Writer.cs b/csharp/Lib/S3/Drivers/Internal/Writer.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Writer.cs rename to csharp/Lib/S3/Drivers/Internal/Writer.cs diff --git a/csharp/lib/S3/Drivers/Internal/Writer.public.cs b/csharp/Lib/S3/Drivers/Internal/Writer.public.cs similarity index 100% rename from csharp/lib/S3/Drivers/Internal/Writer.public.cs rename to csharp/Lib/S3/Drivers/Internal/Writer.public.cs diff --git a/csharp/lib/S3/Drivers/MemoryDriver.cs b/csharp/Lib/S3/Drivers/MemoryDriver.cs similarity index 100% rename from csharp/lib/S3/Drivers/MemoryDriver.cs rename to csharp/Lib/S3/Drivers/MemoryDriver.cs diff --git a/csharp/lib/S3/Drivers/S3Config.cs b/csharp/Lib/S3/Drivers/S3Config.cs similarity index 100% rename from csharp/lib/S3/Drivers/S3Config.cs rename to csharp/Lib/S3/Drivers/S3Config.cs diff --git a/csharp/lib/S3/Drivers/S3Driver.cs b/csharp/Lib/S3/Drivers/S3Driver.cs similarity index 100% rename from csharp/lib/S3/Drivers/S3Driver.cs rename to csharp/Lib/S3/Drivers/S3Driver.cs diff --git a/csharp/lib/S3/Metadata/AggregationLevel.cs b/csharp/Lib/S3/Metadata/AggregationLevel.cs similarity index 100% rename from csharp/lib/S3/Metadata/AggregationLevel.cs rename to csharp/Lib/S3/Metadata/AggregationLevel.cs diff --git a/csharp/lib/S3/Metadata/FieldType.cs b/csharp/Lib/S3/Metadata/FieldType.cs similarity index 100% rename from csharp/lib/S3/Metadata/FieldType.cs rename to csharp/Lib/S3/Metadata/FieldType.cs diff --git a/csharp/lib/S3/Program.cs b/csharp/Lib/S3/Program.cs similarity index 100% rename from csharp/lib/S3/Program.cs rename to csharp/Lib/S3/Program.cs diff --git a/csharp/lib/S3/Records/Fields/Field.cs b/csharp/Lib/S3/Records/Fields/Field.cs similarity index 100% rename from csharp/lib/S3/Records/Fields/Field.cs rename to csharp/Lib/S3/Records/Fields/Field.cs diff --git a/csharp/lib/S3/Records/Fields/NumberField.cs b/csharp/Lib/S3/Records/Fields/NumberField.cs similarity index 100% rename from csharp/lib/S3/Records/Fields/NumberField.cs rename to csharp/Lib/S3/Records/Fields/NumberField.cs diff --git a/csharp/lib/S3/Records/Fields/TextField.cs b/csharp/Lib/S3/Records/Fields/TextField.cs similarity index 100% rename from csharp/lib/S3/Records/Fields/TextField.cs rename to csharp/Lib/S3/Records/Fields/TextField.cs diff --git a/csharp/lib/S3/Records/Fields/TextFrequency.cs b/csharp/Lib/S3/Records/Fields/TextFrequency.cs similarity index 100% rename from csharp/lib/S3/Records/Fields/TextFrequency.cs rename to csharp/Lib/S3/Records/Fields/TextFrequency.cs diff --git a/csharp/lib/S3/Records/Fields/UnitAttribute.cs b/csharp/Lib/S3/Records/Fields/UnitAttribute.cs similarity index 100% rename from csharp/lib/S3/Records/Fields/UnitAttribute.cs rename to csharp/Lib/S3/Records/Fields/UnitAttribute.cs diff --git a/csharp/lib/S3/Records/Fields/WithUnit.cs b/csharp/Lib/S3/Records/Fields/WithUnit.cs similarity index 100% rename from csharp/lib/S3/Records/Fields/WithUnit.cs rename to csharp/Lib/S3/Records/Fields/WithUnit.cs diff --git a/csharp/lib/S3/Records/Operations/Aggregation.cs b/csharp/Lib/S3/Records/Operations/Aggregation.cs similarity index 100% rename from csharp/lib/S3/Records/Operations/Aggregation.cs rename to csharp/Lib/S3/Records/Operations/Aggregation.cs diff --git a/csharp/lib/S3/Records/Operations/Conversion.cs b/csharp/Lib/S3/Records/Operations/Conversion.cs similarity index 100% rename from csharp/lib/S3/Records/Operations/Conversion.cs rename to csharp/Lib/S3/Records/Operations/Conversion.cs diff --git a/csharp/lib/S3/Records/Record.cs b/csharp/Lib/S3/Records/Record.cs similarity index 100% rename from csharp/lib/S3/Records/Record.cs rename to csharp/Lib/S3/Records/Record.cs diff --git a/csharp/lib/S3/Records/Serialization/FieldTag.cs b/csharp/Lib/S3/Records/Serialization/FieldTag.cs similarity index 100% rename from csharp/lib/S3/Records/Serialization/FieldTag.cs rename to csharp/Lib/S3/Records/Serialization/FieldTag.cs diff --git a/csharp/lib/S3/Records/Serialization/Parser.cs b/csharp/Lib/S3/Records/Serialization/Parser.cs similarity index 100% rename from csharp/lib/S3/Records/Serialization/Parser.cs rename to csharp/Lib/S3/Records/Serialization/Parser.cs diff --git a/csharp/lib/S3/Records/Serialization/Serializer.cs b/csharp/Lib/S3/Records/Serialization/Serializer.cs similarity index 100% rename from csharp/lib/S3/Records/Serialization/Serializer.cs rename to csharp/Lib/S3/Records/Serialization/Serializer.cs diff --git a/csharp/lib/S3/Records/Specialized/AggregatedRecord.cs b/csharp/Lib/S3/Records/Specialized/AggregatedRecord.cs similarity index 100% rename from csharp/lib/S3/Records/Specialized/AggregatedRecord.cs rename to csharp/Lib/S3/Records/Specialized/AggregatedRecord.cs diff --git a/csharp/lib/S3/Records/Specialized/TimeStampedRecord.cs b/csharp/Lib/S3/Records/Specialized/TimeStampedRecord.cs similarity index 100% rename from csharp/lib/S3/Records/Specialized/TimeStampedRecord.cs rename to csharp/Lib/S3/Records/Specialized/TimeStampedRecord.cs diff --git a/csharp/lib/S3/S3.csproj b/csharp/Lib/S3/S3.csproj similarity index 60% rename from csharp/lib/S3/S3.csproj rename to csharp/Lib/S3/S3.csproj index 0da1127e5..946c4841f 100644 --- a/csharp/lib/S3/S3.csproj +++ b/csharp/Lib/S3/S3.csproj @@ -1,10 +1,10 @@ - + - - + + diff --git a/csharp/lib/S3/Serialization/JsonConverters.cs b/csharp/Lib/S3/Serialization/JsonConverters.cs similarity index 100% rename from csharp/lib/S3/Serialization/JsonConverters.cs rename to csharp/Lib/S3/Serialization/JsonConverters.cs diff --git a/csharp/lib/StatusApi/Connections/DcConnection.cs b/csharp/Lib/StatusApi/Connections/DcConnection.cs similarity index 100% rename from csharp/lib/StatusApi/Connections/DcConnection.cs rename to csharp/Lib/StatusApi/Connections/DcConnection.cs diff --git a/csharp/lib/StatusApi/Connections/SinglePhaseAcConnection.cs b/csharp/Lib/StatusApi/Connections/SinglePhaseAcConnection.cs similarity index 100% rename from csharp/lib/StatusApi/Connections/SinglePhaseAcConnection.cs rename to csharp/Lib/StatusApi/Connections/SinglePhaseAcConnection.cs diff --git a/csharp/lib/StatusApi/Connections/ThreePhaseAcConnection.cs b/csharp/Lib/StatusApi/Connections/ThreePhaseAcConnection.cs similarity index 100% rename from csharp/lib/StatusApi/Connections/ThreePhaseAcConnection.cs rename to csharp/Lib/StatusApi/Connections/ThreePhaseAcConnection.cs diff --git a/csharp/lib/StatusApi/DeviceType.cs b/csharp/Lib/StatusApi/DeviceType.cs similarity index 100% rename from csharp/lib/StatusApi/DeviceType.cs rename to csharp/Lib/StatusApi/DeviceType.cs diff --git a/csharp/lib/StatusApi/Devices/Battery.cs b/csharp/Lib/StatusApi/Devices/Battery.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/Battery.cs rename to csharp/Lib/StatusApi/Devices/Battery.cs diff --git a/csharp/lib/StatusApi/Devices/DcDcConverter.cs b/csharp/Lib/StatusApi/Devices/DcDcConverter.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/DcDcConverter.cs rename to csharp/Lib/StatusApi/Devices/DcDcConverter.cs diff --git a/csharp/lib/StatusApi/Devices/DcDevice.cs b/csharp/Lib/StatusApi/Devices/DcDevice.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/DcDevice.cs rename to csharp/Lib/StatusApi/Devices/DcDevice.cs diff --git a/csharp/lib/StatusApi/Devices/Device.cs b/csharp/Lib/StatusApi/Devices/Device.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/Device.cs rename to csharp/Lib/StatusApi/Devices/Device.cs diff --git a/csharp/lib/StatusApi/Devices/GridMeter.cs b/csharp/Lib/StatusApi/Devices/GridMeter.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/GridMeter.cs rename to csharp/Lib/StatusApi/Devices/GridMeter.cs diff --git a/csharp/lib/StatusApi/Devices/IPvCoupledDevice.cs b/csharp/Lib/StatusApi/Devices/IPvCoupledDevice.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/IPvCoupledDevice.cs rename to csharp/Lib/StatusApi/Devices/IPvCoupledDevice.cs diff --git a/csharp/lib/StatusApi/Devices/Mppt.cs b/csharp/Lib/StatusApi/Devices/Mppt.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/Mppt.cs rename to csharp/Lib/StatusApi/Devices/Mppt.cs diff --git a/csharp/lib/StatusApi/Devices/SinglePhaseAcDevice.cs b/csharp/Lib/StatusApi/Devices/SinglePhaseAcDevice.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/SinglePhaseAcDevice.cs rename to csharp/Lib/StatusApi/Devices/SinglePhaseAcDevice.cs diff --git a/csharp/lib/StatusApi/Devices/SinglePhaseInverter.cs b/csharp/Lib/StatusApi/Devices/SinglePhaseInverter.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/SinglePhaseInverter.cs rename to csharp/Lib/StatusApi/Devices/SinglePhaseInverter.cs diff --git a/csharp/lib/StatusApi/Devices/SinglePhasePvInverter.cs b/csharp/Lib/StatusApi/Devices/SinglePhasePvInverter.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/SinglePhasePvInverter.cs rename to csharp/Lib/StatusApi/Devices/SinglePhasePvInverter.cs diff --git a/csharp/lib/StatusApi/Devices/ThreePhaseAcDevice.cs b/csharp/Lib/StatusApi/Devices/ThreePhaseAcDevice.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/ThreePhaseAcDevice.cs rename to csharp/Lib/StatusApi/Devices/ThreePhaseAcDevice.cs diff --git a/csharp/lib/StatusApi/Devices/ThreePhaseInverter.cs b/csharp/Lib/StatusApi/Devices/ThreePhaseInverter.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/ThreePhaseInverter.cs rename to csharp/Lib/StatusApi/Devices/ThreePhaseInverter.cs diff --git a/csharp/lib/StatusApi/Devices/ThreePhasePvInverter.cs b/csharp/Lib/StatusApi/Devices/ThreePhasePvInverter.cs similarity index 100% rename from csharp/lib/StatusApi/Devices/ThreePhasePvInverter.cs rename to csharp/Lib/StatusApi/Devices/ThreePhasePvInverter.cs diff --git a/csharp/lib/StatusApi/Phases/AcPhase.cs b/csharp/Lib/StatusApi/Phases/AcPhase.cs similarity index 100% rename from csharp/lib/StatusApi/Phases/AcPhase.cs rename to csharp/Lib/StatusApi/Phases/AcPhase.cs diff --git a/csharp/lib/StatusApi/Phases/Phase.cs b/csharp/Lib/StatusApi/Phases/Phase.cs similarity index 100% rename from csharp/lib/StatusApi/Phases/Phase.cs rename to csharp/Lib/StatusApi/Phases/Phase.cs diff --git a/csharp/lib/StatusApi/StatusApi.csproj b/csharp/Lib/StatusApi/StatusApi.csproj similarity index 75% rename from csharp/lib/StatusApi/StatusApi.csproj rename to csharp/Lib/StatusApi/StatusApi.csproj index bb446855b..f1e4bc0f8 100644 --- a/csharp/lib/StatusApi/StatusApi.csproj +++ b/csharp/Lib/StatusApi/StatusApi.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/StatusApi/Utils.cs b/csharp/Lib/StatusApi/Utils.cs similarity index 100% rename from csharp/lib/StatusApi/Utils.cs rename to csharp/Lib/StatusApi/Utils.cs diff --git a/csharp/lib/StatusData/Current.cs b/csharp/Lib/StatusData/Current.cs similarity index 100% rename from csharp/lib/StatusData/Current.cs rename to csharp/Lib/StatusData/Current.cs diff --git a/csharp/lib/StatusData/Json/Converters.cs b/csharp/Lib/StatusData/Json/Converters.cs similarity index 100% rename from csharp/lib/StatusData/Json/Converters.cs rename to csharp/Lib/StatusData/Json/Converters.cs diff --git a/csharp/lib/StatusData/Json/CurrentConverter.cs b/csharp/Lib/StatusData/Json/CurrentConverter.cs similarity index 100% rename from csharp/lib/StatusData/Json/CurrentConverter.cs rename to csharp/Lib/StatusData/Json/CurrentConverter.cs diff --git a/csharp/lib/StatusData/Json/PowerConverter.cs b/csharp/Lib/StatusData/Json/PowerConverter.cs similarity index 100% rename from csharp/lib/StatusData/Json/PowerConverter.cs rename to csharp/Lib/StatusData/Json/PowerConverter.cs diff --git a/csharp/lib/StatusData/Json/ResistanceConverter.cs b/csharp/Lib/StatusData/Json/ResistanceConverter.cs similarity index 100% rename from csharp/lib/StatusData/Json/ResistanceConverter.cs rename to csharp/Lib/StatusData/Json/ResistanceConverter.cs diff --git a/csharp/lib/StatusData/Json/VoltageConverter.cs b/csharp/Lib/StatusData/Json/VoltageConverter.cs similarity index 100% rename from csharp/lib/StatusData/Json/VoltageConverter.cs rename to csharp/Lib/StatusData/Json/VoltageConverter.cs diff --git a/csharp/lib/StatusData/Power.cs b/csharp/Lib/StatusData/Power.cs similarity index 100% rename from csharp/lib/StatusData/Power.cs rename to csharp/Lib/StatusData/Power.cs diff --git a/csharp/lib/StatusData/Resistance.cs b/csharp/Lib/StatusData/Resistance.cs similarity index 100% rename from csharp/lib/StatusData/Resistance.cs rename to csharp/Lib/StatusData/Resistance.cs diff --git a/csharp/lib/StatusData/State.cs b/csharp/Lib/StatusData/State.cs similarity index 100% rename from csharp/lib/StatusData/State.cs rename to csharp/Lib/StatusData/State.cs diff --git a/csharp/lib/StatusData/StatusData.csproj b/csharp/Lib/StatusData/StatusData.csproj similarity index 77% rename from csharp/lib/StatusData/StatusData.csproj rename to csharp/Lib/StatusData/StatusData.csproj index 22522002f..69d164c4f 100644 --- a/csharp/lib/StatusData/StatusData.csproj +++ b/csharp/Lib/StatusData/StatusData.csproj @@ -1,5 +1,5 @@ - + Library diff --git a/csharp/lib/StatusData/Units.cs b/csharp/Lib/StatusData/Units.cs similarity index 100% rename from csharp/lib/StatusData/Units.cs rename to csharp/Lib/StatusData/Units.cs diff --git a/csharp/lib/StatusData/Voltage.cs b/csharp/Lib/StatusData/Voltage.cs similarity index 100% rename from csharp/lib/StatusData/Voltage.cs rename to csharp/Lib/StatusData/Voltage.cs diff --git a/csharp/lib/SysTools/Edges/RemoteCommandToProcess.cs b/csharp/Lib/SysTools/Edges/RemoteCommandToProcess.cs similarity index 100% rename from csharp/lib/SysTools/Edges/RemoteCommandToProcess.cs rename to csharp/Lib/SysTools/Edges/RemoteCommandToProcess.cs diff --git a/csharp/lib/SysTools/Edges/RemotePathToRemoteCommand.cs b/csharp/Lib/SysTools/Edges/RemotePathToRemoteCommand.cs similarity index 100% rename from csharp/lib/SysTools/Edges/RemotePathToRemoteCommand.cs rename to csharp/Lib/SysTools/Edges/RemotePathToRemoteCommand.cs diff --git a/csharp/lib/SysTools/Edges/SshHostToRemoteCommand.cs b/csharp/Lib/SysTools/Edges/SshHostToRemoteCommand.cs similarity index 100% rename from csharp/lib/SysTools/Edges/SshHostToRemoteCommand.cs rename to csharp/Lib/SysTools/Edges/SshHostToRemoteCommand.cs diff --git a/csharp/lib/SysTools/Edges/SshHostToRemotePath.cs b/csharp/Lib/SysTools/Edges/SshHostToRemotePath.cs similarity index 100% rename from csharp/lib/SysTools/Edges/SshHostToRemotePath.cs rename to csharp/Lib/SysTools/Edges/SshHostToRemotePath.cs diff --git a/csharp/lib/SysTools/Edges/StringToCommand.cs b/csharp/Lib/SysTools/Edges/StringToCommand.cs similarity index 100% rename from csharp/lib/SysTools/Edges/StringToCommand.cs rename to csharp/Lib/SysTools/Edges/StringToCommand.cs diff --git a/csharp/lib/SysTools/Edges/StringToProcess.cs b/csharp/Lib/SysTools/Edges/StringToProcess.cs similarity index 100% rename from csharp/lib/SysTools/Edges/StringToProcess.cs rename to csharp/Lib/SysTools/Edges/StringToProcess.cs diff --git a/csharp/lib/SysTools/Edges/StringToRemotePath.cs b/csharp/Lib/SysTools/Edges/StringToRemotePath.cs similarity index 100% rename from csharp/lib/SysTools/Edges/StringToRemotePath.cs rename to csharp/Lib/SysTools/Edges/StringToRemotePath.cs diff --git a/csharp/lib/SysTools/Edges/StringToSysPath.cs b/csharp/Lib/SysTools/Edges/StringToSysPath.cs similarity index 100% rename from csharp/lib/SysTools/Edges/StringToSysPath.cs rename to csharp/Lib/SysTools/Edges/StringToSysPath.cs diff --git a/csharp/lib/SysTools/Edges/SysCommandToProcess.cs b/csharp/Lib/SysTools/Edges/SysCommandToProcess.cs similarity index 100% rename from csharp/lib/SysTools/Edges/SysCommandToProcess.cs rename to csharp/Lib/SysTools/Edges/SysCommandToProcess.cs diff --git a/csharp/lib/SysTools/Edges/SysCommandToRemoteCommand.cs b/csharp/Lib/SysTools/Edges/SysCommandToRemoteCommand.cs similarity index 100% rename from csharp/lib/SysTools/Edges/SysCommandToRemoteCommand.cs rename to csharp/Lib/SysTools/Edges/SysCommandToRemoteCommand.cs diff --git a/csharp/lib/SysTools/Edges/SysPathToProcess.cs b/csharp/Lib/SysTools/Edges/SysPathToProcess.cs similarity index 100% rename from csharp/lib/SysTools/Edges/SysPathToProcess.cs rename to csharp/Lib/SysTools/Edges/SysPathToProcess.cs diff --git a/csharp/lib/SysTools/Edges/SysPathToRemotePath.cs b/csharp/Lib/SysTools/Edges/SysPathToRemotePath.cs similarity index 100% rename from csharp/lib/SysTools/Edges/SysPathToRemotePath.cs rename to csharp/Lib/SysTools/Edges/SysPathToRemotePath.cs diff --git a/csharp/lib/SysTools/Edges/SysPathToSysCommand.cs b/csharp/Lib/SysTools/Edges/SysPathToSysCommand.cs similarity index 100% rename from csharp/lib/SysTools/Edges/SysPathToSysCommand.cs rename to csharp/Lib/SysTools/Edges/SysPathToSysCommand.cs diff --git a/csharp/lib/SysTools/FileIo.cs b/csharp/Lib/SysTools/FileIo.cs similarity index 100% rename from csharp/lib/SysTools/FileIo.cs rename to csharp/Lib/SysTools/FileIo.cs diff --git a/csharp/lib/SysTools/Process/AsyncProcess.cs b/csharp/Lib/SysTools/Process/AsyncProcess.cs similarity index 100% rename from csharp/lib/SysTools/Process/AsyncProcess.cs rename to csharp/Lib/SysTools/Process/AsyncProcess.cs diff --git a/csharp/lib/SysTools/Process/ProcessResult.cs b/csharp/Lib/SysTools/Process/ProcessResult.cs similarity index 100% rename from csharp/lib/SysTools/Process/ProcessResult.cs rename to csharp/Lib/SysTools/Process/ProcessResult.cs diff --git a/csharp/lib/SysTools/Process/SyncProcess.cs b/csharp/Lib/SysTools/Process/SyncProcess.cs similarity index 100% rename from csharp/lib/SysTools/Process/SyncProcess.cs rename to csharp/Lib/SysTools/Process/SyncProcess.cs diff --git a/csharp/lib/SysTools/Remote/RemoteCommand.cs b/csharp/Lib/SysTools/Remote/RemoteCommand.cs similarity index 100% rename from csharp/lib/SysTools/Remote/RemoteCommand.cs rename to csharp/Lib/SysTools/Remote/RemoteCommand.cs diff --git a/csharp/lib/SysTools/Remote/RemoteFileIo.cs b/csharp/Lib/SysTools/Remote/RemoteFileIo.cs similarity index 100% rename from csharp/lib/SysTools/Remote/RemoteFileIo.cs rename to csharp/Lib/SysTools/Remote/RemoteFileIo.cs diff --git a/csharp/lib/SysTools/Remote/RemotePath.cs b/csharp/Lib/SysTools/Remote/RemotePath.cs similarity index 100% rename from csharp/lib/SysTools/Remote/RemotePath.cs rename to csharp/Lib/SysTools/Remote/RemotePath.cs diff --git a/csharp/lib/SysTools/Remote/SshHost.cs b/csharp/Lib/SysTools/Remote/SshHost.cs similarity index 100% rename from csharp/lib/SysTools/Remote/SshHost.cs rename to csharp/Lib/SysTools/Remote/SshHost.cs diff --git a/csharp/lib/SysTools/SysCommand.cs b/csharp/Lib/SysTools/SysCommand.cs similarity index 100% rename from csharp/lib/SysTools/SysCommand.cs rename to csharp/Lib/SysTools/SysCommand.cs diff --git a/csharp/lib/SysTools/SysDirs.cs b/csharp/Lib/SysTools/SysDirs.cs similarity index 100% rename from csharp/lib/SysTools/SysDirs.cs rename to csharp/Lib/SysTools/SysDirs.cs diff --git a/csharp/lib/SysTools/SysPath.cs b/csharp/Lib/SysTools/SysPath.cs similarity index 100% rename from csharp/lib/SysTools/SysPath.cs rename to csharp/Lib/SysTools/SysPath.cs diff --git a/csharp/lib/SysTools/SysTools.csproj b/csharp/Lib/SysTools/SysTools.csproj similarity index 75% rename from csharp/lib/SysTools/SysTools.csproj rename to csharp/Lib/SysTools/SysTools.csproj index aa11972a1..9fd38651b 100644 --- a/csharp/lib/SysTools/SysTools.csproj +++ b/csharp/Lib/SysTools/SysTools.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/SysTools/Utils/ConsoleUtils.cs b/csharp/Lib/SysTools/Utils/ConsoleUtils.cs similarity index 100% rename from csharp/lib/SysTools/Utils/ConsoleUtils.cs rename to csharp/Lib/SysTools/Utils/ConsoleUtils.cs diff --git a/csharp/lib/SysTools/Utils/EnumerableUtils.cs b/csharp/Lib/SysTools/Utils/EnumerableUtils.cs similarity index 100% rename from csharp/lib/SysTools/Utils/EnumerableUtils.cs rename to csharp/Lib/SysTools/Utils/EnumerableUtils.cs diff --git a/csharp/lib/SysTools/Utils/StringUtils.cs b/csharp/Lib/SysTools/Utils/StringUtils.cs similarity index 100% rename from csharp/lib/SysTools/Utils/StringUtils.cs rename to csharp/Lib/SysTools/Utils/StringUtils.cs diff --git a/csharp/lib/SysTools/Utils/Utils.cs b/csharp/Lib/SysTools/Utils/Utils.cs similarity index 100% rename from csharp/lib/SysTools/Utils/Utils.cs rename to csharp/Lib/SysTools/Utils/Utils.cs diff --git a/csharp/Lib/Time/Time.csproj b/csharp/Lib/Time/Time.csproj new file mode 100644 index 000000000..e971a1f7d --- /dev/null +++ b/csharp/Lib/Time/Time.csproj @@ -0,0 +1,3 @@ + + + diff --git a/csharp/lib/Time/Unix/UnixTime.Compare.cs b/csharp/Lib/Time/Unix/UnixTime.Compare.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTime.Compare.cs rename to csharp/Lib/Time/Unix/UnixTime.Compare.cs diff --git a/csharp/lib/Time/Unix/UnixTime.Constructors.cs b/csharp/Lib/Time/Unix/UnixTime.Constructors.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTime.Constructors.cs rename to csharp/Lib/Time/Unix/UnixTime.Constructors.cs diff --git a/csharp/lib/Time/Unix/UnixTime.Converters.cs b/csharp/Lib/Time/Unix/UnixTime.Converters.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTime.Converters.cs rename to csharp/Lib/Time/Unix/UnixTime.Converters.cs diff --git a/csharp/lib/Time/Unix/UnixTime.Operators.cs b/csharp/Lib/Time/Unix/UnixTime.Operators.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTime.Operators.cs rename to csharp/Lib/Time/Unix/UnixTime.Operators.cs diff --git a/csharp/lib/Time/Unix/UnixTime.Overrides.cs b/csharp/Lib/Time/Unix/UnixTime.Overrides.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTime.Overrides.cs rename to csharp/Lib/Time/Unix/UnixTime.Overrides.cs diff --git a/csharp/lib/Time/Unix/UnixTime.cs b/csharp/Lib/Time/Unix/UnixTime.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTime.cs rename to csharp/Lib/Time/Unix/UnixTime.cs diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Compare.cs b/csharp/Lib/Time/Unix/UnixTimeDelta.Compare.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTimeDelta.Compare.cs rename to csharp/Lib/Time/Unix/UnixTimeDelta.Compare.cs diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Constructors.cs b/csharp/Lib/Time/Unix/UnixTimeDelta.Constructors.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTimeDelta.Constructors.cs rename to csharp/Lib/Time/Unix/UnixTimeDelta.Constructors.cs diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Operators.cs b/csharp/Lib/Time/Unix/UnixTimeDelta.Operators.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTimeDelta.Operators.cs rename to csharp/Lib/Time/Unix/UnixTimeDelta.Operators.cs diff --git a/csharp/lib/Time/Unix/UnixTimeDelta.Overrides.cs b/csharp/Lib/Time/Unix/UnixTimeDelta.Overrides.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTimeDelta.Overrides.cs rename to csharp/Lib/Time/Unix/UnixTimeDelta.Overrides.cs diff --git a/csharp/lib/Time/Unix/UnixTimeDeltaExtensions.cs b/csharp/Lib/Time/Unix/UnixTimeDeltaExtensions.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTimeDeltaExtensions.cs rename to csharp/Lib/Time/Unix/UnixTimeDeltaExtensions.cs diff --git a/csharp/lib/Time/Unix/UnixTimeSpan.cs b/csharp/Lib/Time/Unix/UnixTimeSpan.cs similarity index 100% rename from csharp/lib/Time/Unix/UnixTimeSpan.cs rename to csharp/Lib/Time/Unix/UnixTimeSpan.cs diff --git a/csharp/lib/Utils/ArrayExtensions.cs b/csharp/Lib/Utils/ArrayExtensions.cs similarity index 100% rename from csharp/lib/Utils/ArrayExtensions.cs rename to csharp/Lib/Utils/ArrayExtensions.cs diff --git a/csharp/lib/Utils/AsyncDelegates.cs b/csharp/Lib/Utils/AsyncDelegates.cs similarity index 100% rename from csharp/lib/Utils/AsyncDelegates.cs rename to csharp/Lib/Utils/AsyncDelegates.cs diff --git a/csharp/lib/Utils/AsyncEnumerableEx.cs b/csharp/Lib/Utils/AsyncEnumerableEx.cs similarity index 100% rename from csharp/lib/Utils/AsyncEnumerableEx.cs rename to csharp/Lib/Utils/AsyncEnumerableEx.cs diff --git a/csharp/lib/Utils/AutoComplete.cs b/csharp/Lib/Utils/AutoComplete.cs similarity index 100% rename from csharp/lib/Utils/AutoComplete.cs rename to csharp/Lib/Utils/AutoComplete.cs diff --git a/csharp/lib/Utils/CliCommandUtils.cs b/csharp/Lib/Utils/CliCommandUtils.cs similarity index 100% rename from csharp/lib/Utils/CliCommandUtils.cs rename to csharp/Lib/Utils/CliCommandUtils.cs diff --git a/csharp/lib/Utils/ConsoleUtils.cs b/csharp/Lib/Utils/ConsoleUtils.cs similarity index 100% rename from csharp/lib/Utils/ConsoleUtils.cs rename to csharp/Lib/Utils/ConsoleUtils.cs diff --git a/csharp/lib/Utils/DecimalUtils.cs b/csharp/Lib/Utils/DecimalUtils.cs similarity index 100% rename from csharp/lib/Utils/DecimalUtils.cs rename to csharp/Lib/Utils/DecimalUtils.cs diff --git a/csharp/lib/Utils/DictObservables.cs b/csharp/Lib/Utils/DictObservables.cs similarity index 100% rename from csharp/lib/Utils/DictObservables.cs rename to csharp/Lib/Utils/DictObservables.cs diff --git a/csharp/lib/Utils/Disposable.cs b/csharp/Lib/Utils/Disposable.cs similarity index 100% rename from csharp/lib/Utils/Disposable.cs rename to csharp/Lib/Utils/Disposable.cs diff --git a/csharp/lib/Utils/EnumerableUtils.cs b/csharp/Lib/Utils/EnumerableUtils.cs similarity index 100% rename from csharp/lib/Utils/EnumerableUtils.cs rename to csharp/Lib/Utils/EnumerableUtils.cs diff --git a/csharp/lib/Utils/ExceptionHandling.cs b/csharp/Lib/Utils/ExceptionHandling.cs similarity index 100% rename from csharp/lib/Utils/ExceptionHandling.cs rename to csharp/Lib/Utils/ExceptionHandling.cs diff --git a/csharp/lib/Utils/FileSystem.cs b/csharp/Lib/Utils/FileSystem.cs similarity index 100% rename from csharp/lib/Utils/FileSystem.cs rename to csharp/Lib/Utils/FileSystem.cs diff --git a/csharp/lib/Utils/JsonNodeAccessors.cs b/csharp/Lib/Utils/JsonNodeAccessors.cs similarity index 100% rename from csharp/lib/Utils/JsonNodeAccessors.cs rename to csharp/Lib/Utils/JsonNodeAccessors.cs diff --git a/csharp/lib/Utils/Maybe.cs b/csharp/Lib/Utils/Maybe.cs similarity index 100% rename from csharp/lib/Utils/Maybe.cs rename to csharp/Lib/Utils/Maybe.cs diff --git a/csharp/lib/Utils/Net/NetUtils.cs b/csharp/Lib/Utils/Net/NetUtils.cs similarity index 100% rename from csharp/lib/Utils/Net/NetUtils.cs rename to csharp/Lib/Utils/Net/NetUtils.cs diff --git a/csharp/lib/Utils/Net/PingExtensions.cs b/csharp/Lib/Utils/Net/PingExtensions.cs similarity index 100% rename from csharp/lib/Utils/Net/PingExtensions.cs rename to csharp/Lib/Utils/Net/PingExtensions.cs diff --git a/csharp/lib/Utils/Net/UdpExtensions.cs b/csharp/Lib/Utils/Net/UdpExtensions.cs similarity index 100% rename from csharp/lib/Utils/Net/UdpExtensions.cs rename to csharp/Lib/Utils/Net/UdpExtensions.cs diff --git a/csharp/lib/Utils/None.cs b/csharp/Lib/Utils/None.cs similarity index 100% rename from csharp/lib/Utils/None.cs rename to csharp/Lib/Utils/None.cs diff --git a/csharp/lib/Utils/NullableUtils.cs b/csharp/Lib/Utils/NullableUtils.cs similarity index 100% rename from csharp/lib/Utils/NullableUtils.cs rename to csharp/Lib/Utils/NullableUtils.cs diff --git a/csharp/lib/Utils/ObservableExceptionHandling.cs b/csharp/Lib/Utils/ObservableExceptionHandling.cs similarity index 100% rename from csharp/lib/Utils/ObservableExceptionHandling.cs rename to csharp/Lib/Utils/ObservableExceptionHandling.cs diff --git a/csharp/lib/Utils/ObservableUtils.cs b/csharp/Lib/Utils/ObservableUtils.cs similarity index 100% rename from csharp/lib/Utils/ObservableUtils.cs rename to csharp/Lib/Utils/ObservableUtils.cs diff --git a/csharp/lib/Utils/PointFree.cs b/csharp/Lib/Utils/PointFree.cs similarity index 100% rename from csharp/lib/Utils/PointFree.cs rename to csharp/Lib/Utils/PointFree.cs diff --git a/csharp/lib/Utils/SshHost.cs b/csharp/Lib/Utils/SshHost.cs similarity index 100% rename from csharp/lib/Utils/SshHost.cs rename to csharp/Lib/Utils/SshHost.cs diff --git a/csharp/lib/Utils/StreamExtensions.cs b/csharp/Lib/Utils/StreamExtensions.cs similarity index 100% rename from csharp/lib/Utils/StreamExtensions.cs rename to csharp/Lib/Utils/StreamExtensions.cs diff --git a/csharp/lib/Utils/StringUtils.cs b/csharp/Lib/Utils/StringUtils.cs similarity index 100% rename from csharp/lib/Utils/StringUtils.cs rename to csharp/Lib/Utils/StringUtils.cs diff --git a/csharp/lib/Utils/TaskUtils.cs b/csharp/Lib/Utils/TaskUtils.cs similarity index 100% rename from csharp/lib/Utils/TaskUtils.cs rename to csharp/Lib/Utils/TaskUtils.cs diff --git a/csharp/lib/Utils/TextBlock.cs b/csharp/Lib/Utils/TextBlock.cs similarity index 100% rename from csharp/lib/Utils/TextBlock.cs rename to csharp/Lib/Utils/TextBlock.cs diff --git a/csharp/lib/Utils/Try/Operators.async.cs b/csharp/Lib/Utils/Try/Operators.async.cs similarity index 100% rename from csharp/lib/Utils/Try/Operators.async.cs rename to csharp/Lib/Utils/Try/Operators.async.cs diff --git a/csharp/lib/Utils/Try/Operators.sync.cs b/csharp/Lib/Utils/Try/Operators.sync.cs similarity index 100% rename from csharp/lib/Utils/Try/Operators.sync.cs rename to csharp/Lib/Utils/Try/Operators.sync.cs diff --git a/csharp/lib/Utils/Try/Policy.cs b/csharp/Lib/Utils/Try/Policy.cs similarity index 100% rename from csharp/lib/Utils/Try/Policy.cs rename to csharp/Lib/Utils/Try/Policy.cs diff --git a/csharp/lib/Utils/Try/TryAsync.async.cs b/csharp/Lib/Utils/Try/TryAsync.async.cs similarity index 100% rename from csharp/lib/Utils/Try/TryAsync.async.cs rename to csharp/Lib/Utils/Try/TryAsync.async.cs diff --git a/csharp/lib/Utils/Try/TryAsync.cs b/csharp/Lib/Utils/Try/TryAsync.cs similarity index 100% rename from csharp/lib/Utils/Try/TryAsync.cs rename to csharp/Lib/Utils/Try/TryAsync.cs diff --git a/csharp/lib/Utils/Try/TryAsync.sync.cs b/csharp/Lib/Utils/Try/TryAsync.sync.cs similarity index 100% rename from csharp/lib/Utils/Try/TryAsync.sync.cs rename to csharp/Lib/Utils/Try/TryAsync.sync.cs diff --git a/csharp/lib/Utils/Try/TrySync.async.cs b/csharp/Lib/Utils/Try/TrySync.async.cs similarity index 100% rename from csharp/lib/Utils/Try/TrySync.async.cs rename to csharp/Lib/Utils/Try/TrySync.async.cs diff --git a/csharp/lib/Utils/Try/TrySync.cs b/csharp/Lib/Utils/Try/TrySync.cs similarity index 100% rename from csharp/lib/Utils/Try/TrySync.cs rename to csharp/Lib/Utils/Try/TrySync.cs diff --git a/csharp/lib/Utils/Try/TrySync.sync.cs b/csharp/Lib/Utils/Try/TrySync.sync.cs similarity index 100% rename from csharp/lib/Utils/Try/TrySync.sync.cs rename to csharp/Lib/Utils/Try/TrySync.sync.cs diff --git a/csharp/lib/Utils/Units.cs b/csharp/Lib/Utils/Units.cs similarity index 100% rename from csharp/lib/Utils/Units.cs rename to csharp/Lib/Utils/Units.cs diff --git a/csharp/lib/Utils/Utils.cs b/csharp/Lib/Utils/Utils.cs similarity index 100% rename from csharp/lib/Utils/Utils.cs rename to csharp/Lib/Utils/Utils.cs diff --git a/csharp/lib/Utils/Utils.csproj b/csharp/Lib/Utils/Utils.csproj similarity index 87% rename from csharp/lib/Utils/Utils.csproj rename to csharp/Lib/Utils/Utils.csproj index 222f85663..59af027d7 100644 --- a/csharp/lib/Utils/Utils.csproj +++ b/csharp/Lib/Utils/Utils.csproj @@ -1,5 +1,5 @@ - + diff --git a/csharp/lib/Utils/Utils.sln b/csharp/Lib/Utils/Utils.sln similarity index 100% rename from csharp/lib/Utils/Utils.sln rename to csharp/Lib/Utils/Utils.sln diff --git a/csharp/lib/Utils/ValueTupleUtils.cs b/csharp/Lib/Utils/ValueTupleUtils.cs similarity index 100% rename from csharp/lib/Utils/ValueTupleUtils.cs rename to csharp/Lib/Utils/ValueTupleUtils.cs diff --git a/csharp/lib/Victron/VeDBus/Program.cs b/csharp/Lib/Victron/VeDBus/Program.cs similarity index 100% rename from csharp/lib/Victron/VeDBus/Program.cs rename to csharp/Lib/Victron/VeDBus/Program.cs diff --git a/csharp/lib/Victron/VeDBus/VeDBus.cs b/csharp/Lib/Victron/VeDBus/VeDBus.cs similarity index 100% rename from csharp/lib/Victron/VeDBus/VeDBus.cs rename to csharp/Lib/Victron/VeDBus/VeDBus.cs diff --git a/csharp/lib/Victron/VeDBus/VeDBus.csproj b/csharp/Lib/Victron/VeDBus/VeDBus.csproj similarity index 88% rename from csharp/lib/Victron/VeDBus/VeDBus.csproj rename to csharp/Lib/Victron/VeDBus/VeDBus.csproj index 5f986d84c..fe0000124 100644 --- a/csharp/lib/Victron/VeDBus/VeDBus.csproj +++ b/csharp/Lib/Victron/VeDBus/VeDBus.csproj @@ -1,6 +1,6 @@ - + diff --git a/csharp/lib/Victron/VeDBus/VeDBusApi.cs b/csharp/Lib/Victron/VeDBus/VeDBusApi.cs similarity index 100% rename from csharp/lib/Victron/VeDBus/VeDBusApi.cs rename to csharp/Lib/Victron/VeDBus/VeDBusApi.cs diff --git a/csharp/lib/Victron/VeDBus/VeDbusService.cs b/csharp/Lib/Victron/VeDBus/VeDbusService.cs similarity index 100% rename from csharp/lib/Victron/VeDBus/VeDbusService.cs rename to csharp/Lib/Victron/VeDBus/VeDbusService.cs diff --git a/csharp/lib/Victron/VeDBus/VeProperties.Dbus.cs b/csharp/Lib/Victron/VeDBus/VeProperties.Dbus.cs similarity index 100% rename from csharp/lib/Victron/VeDBus/VeProperties.Dbus.cs rename to csharp/Lib/Victron/VeDBus/VeProperties.Dbus.cs diff --git a/csharp/lib/Victron/VeDBus/VeProperties.cs b/csharp/Lib/Victron/VeDBus/VeProperties.cs similarity index 100% rename from csharp/lib/Victron/VeDBus/VeProperties.cs rename to csharp/Lib/Victron/VeDBus/VeProperties.cs diff --git a/csharp/lib/Victron/VeDBus/VeProperty.cs b/csharp/Lib/Victron/VeDBus/VeProperty.cs similarity index 100% rename from csharp/lib/Victron/VeDBus/VeProperty.cs rename to csharp/Lib/Victron/VeDBus/VeProperty.cs diff --git a/csharp/lib/Victron/VictronVRM/Detail.cs b/csharp/Lib/Victron/VictronVRM/Detail.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Detail.cs rename to csharp/Lib/Victron/VictronVRM/Detail.cs diff --git a/csharp/lib/Victron/VictronVRM/Details.cs b/csharp/Lib/Victron/VictronVRM/Details.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Details.cs rename to csharp/Lib/Victron/VictronVRM/Details.cs diff --git a/csharp/lib/Victron/VictronVRM/Device.cs b/csharp/Lib/Victron/VictronVRM/Device.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Device.cs rename to csharp/Lib/Victron/VictronVRM/Device.cs diff --git a/csharp/lib/Victron/VictronVRM/FlurlExtensions.cs b/csharp/Lib/Victron/VictronVRM/FlurlExtensions.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/FlurlExtensions.cs rename to csharp/Lib/Victron/VictronVRM/FlurlExtensions.cs diff --git a/csharp/lib/Victron/VictronVRM/Installation.Settings.cs b/csharp/Lib/Victron/VictronVRM/Installation.Settings.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Installation.Settings.cs rename to csharp/Lib/Victron/VictronVRM/Installation.Settings.cs diff --git a/csharp/lib/Victron/VictronVRM/Installation.Tags.cs b/csharp/Lib/Victron/VictronVRM/Installation.Tags.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Installation.Tags.cs rename to csharp/Lib/Victron/VictronVRM/Installation.Tags.cs diff --git a/csharp/lib/Victron/VictronVRM/Installation.cs b/csharp/Lib/Victron/VictronVRM/Installation.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Installation.cs rename to csharp/Lib/Victron/VictronVRM/Installation.cs diff --git a/csharp/lib/Victron/VictronVRM/Reply.cs b/csharp/Lib/Victron/VictronVRM/Reply.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Reply.cs rename to csharp/Lib/Victron/VictronVRM/Reply.cs diff --git a/csharp/lib/Victron/VictronVRM/Requests.cs b/csharp/Lib/Victron/VictronVRM/Requests.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Requests.cs rename to csharp/Lib/Victron/VictronVRM/Requests.cs diff --git a/csharp/lib/Victron/VictronVRM/Settings.cs b/csharp/Lib/Victron/VictronVRM/Settings.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/Settings.cs rename to csharp/Lib/Victron/VictronVRM/Settings.cs diff --git a/csharp/lib/Victron/VictronVRM/VictronVRM.csproj b/csharp/Lib/Victron/VictronVRM/VictronVRM.csproj similarity index 92% rename from csharp/lib/Victron/VictronVRM/VictronVRM.csproj rename to csharp/Lib/Victron/VictronVRM/VictronVRM.csproj index 4370080ea..f37c8f354 100644 --- a/csharp/lib/Victron/VictronVRM/VictronVRM.csproj +++ b/csharp/Lib/Victron/VictronVRM/VictronVRM.csproj @@ -1,6 +1,6 @@ - + full diff --git a/csharp/lib/Victron/VictronVRM/VrmAccount.cs b/csharp/Lib/Victron/VictronVRM/VrmAccount.cs similarity index 100% rename from csharp/lib/Victron/VictronVRM/VrmAccount.cs rename to csharp/Lib/Victron/VictronVRM/VrmAccount.cs diff --git a/csharp/lib/WebServer/ContentType.cs b/csharp/Lib/WebServer/ContentType.cs similarity index 100% rename from csharp/lib/WebServer/ContentType.cs rename to csharp/Lib/WebServer/ContentType.cs diff --git a/csharp/lib/WebServer/Default.cs b/csharp/Lib/WebServer/Default.cs similarity index 100% rename from csharp/lib/WebServer/Default.cs rename to csharp/Lib/WebServer/Default.cs diff --git a/csharp/lib/WebServer/HttpExtensions.cs b/csharp/Lib/WebServer/HttpExtensions.cs similarity index 100% rename from csharp/lib/WebServer/HttpExtensions.cs rename to csharp/Lib/WebServer/HttpExtensions.cs diff --git a/csharp/lib/WebServer/HttpHeader.cs b/csharp/Lib/WebServer/HttpHeader.cs similarity index 100% rename from csharp/lib/WebServer/HttpHeader.cs rename to csharp/Lib/WebServer/HttpHeader.cs diff --git a/csharp/lib/WebServer/HttpMethod.cs b/csharp/Lib/WebServer/HttpMethod.cs similarity index 100% rename from csharp/lib/WebServer/HttpMethod.cs rename to csharp/Lib/WebServer/HttpMethod.cs diff --git a/csharp/lib/WebServer/HttpRequest.cs b/csharp/Lib/WebServer/HttpRequest.cs similarity index 100% rename from csharp/lib/WebServer/HttpRequest.cs rename to csharp/Lib/WebServer/HttpRequest.cs diff --git a/csharp/lib/WebServer/HttpResponse.cs b/csharp/Lib/WebServer/HttpResponse.cs similarity index 100% rename from csharp/lib/WebServer/HttpResponse.cs rename to csharp/Lib/WebServer/HttpResponse.cs diff --git a/csharp/lib/WebServer/WebServer.cs b/csharp/Lib/WebServer/WebServer.cs similarity index 100% rename from csharp/lib/WebServer/WebServer.cs rename to csharp/Lib/WebServer/WebServer.cs diff --git a/csharp/lib/WebServer/WebServer.csproj b/csharp/Lib/WebServer/WebServer.csproj similarity index 76% rename from csharp/lib/WebServer/WebServer.csproj rename to csharp/Lib/WebServer/WebServer.csproj index 8063be2ce..00c76841c 100644 --- a/csharp/lib/WebServer/WebServer.csproj +++ b/csharp/Lib/WebServer/WebServer.csproj @@ -1,6 +1,6 @@ - + @@ -13,7 +13,7 @@ - + diff --git a/csharp/lib/Wireformat/WireFormat.csproj.DotSettings b/csharp/Lib/Wireformat/WireFormat.csproj.DotSettings similarity index 100% rename from csharp/lib/Wireformat/WireFormat.csproj.DotSettings rename to csharp/Lib/Wireformat/WireFormat.csproj.DotSettings diff --git a/csharp/lib/Wireformat/build_proto.sh b/csharp/Lib/Wireformat/build_proto.sh similarity index 100% rename from csharp/lib/Wireformat/build_proto.sh rename to csharp/Lib/Wireformat/build_proto.sh diff --git a/csharp/lib/Wireformat/package-lock.json b/csharp/Lib/Wireformat/package-lock.json similarity index 100% rename from csharp/lib/Wireformat/package-lock.json rename to csharp/Lib/Wireformat/package-lock.json diff --git a/csharp/lib/Wireformat/package.json b/csharp/Lib/Wireformat/package.json similarity index 100% rename from csharp/lib/Wireformat/package.json rename to csharp/Lib/Wireformat/package.json diff --git a/csharp/lib/Wireformat/proto/Payload.proto b/csharp/Lib/Wireformat/proto/Payload.proto similarity index 100% rename from csharp/lib/Wireformat/proto/Payload.proto rename to csharp/Lib/Wireformat/proto/Payload.proto diff --git a/csharp/lib/Wireformat/proto/VictronV1/BatteryStatus48TL.proto b/csharp/Lib/Wireformat/proto/VictronV1/BatteryStatus48TL.proto similarity index 100% rename from csharp/lib/Wireformat/proto/VictronV1/BatteryStatus48TL.proto rename to csharp/Lib/Wireformat/proto/VictronV1/BatteryStatus48TL.proto diff --git a/csharp/lib/Wireformat/proto/VictronV1/Device.proto b/csharp/Lib/Wireformat/proto/VictronV1/Device.proto similarity index 100% rename from csharp/lib/Wireformat/proto/VictronV1/Device.proto rename to csharp/Lib/Wireformat/proto/VictronV1/Device.proto diff --git a/csharp/lib/Wireformat/proto/VictronV1/VictronTopologyV1.proto b/csharp/Lib/Wireformat/proto/VictronV1/VictronTopologyV1.proto similarity index 100% rename from csharp/lib/Wireformat/proto/VictronV1/VictronTopologyV1.proto rename to csharp/Lib/Wireformat/proto/VictronV1/VictronTopologyV1.proto diff --git a/csharp/app/Backend/db.sqlite b/csharp/app/Backend/db.sqlite deleted file mode 100644 index fc3ad2ed8207696af0e245f9f64a04984997fcba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290816 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

)vO`dF$*ul2_5nMn15SWmZTwepLlvE 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

D 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

s%ile-&AEBHK#S-WiWBWjhu~O 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

{3`(T` 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 Si3S$9goLy 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 qUG`Zih#2=s@yr-!q - - - - - - - - - - - - - - - diff --git a/csharp/app/SaliMax/SaliMax.csproj b/csharp/app/SaliMax/SaliMax.csproj deleted file mode 100644 index 2c2d378bd..000000000 --- a/csharp/app/SaliMax/SaliMax.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/csharp/lib/Channels/Channels.csproj b/csharp/lib/Channels/Channels.csproj deleted file mode 100644 index 38b2fa318..000000000 --- a/csharp/lib/Channels/Channels.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/csharp/lib/Time/Time.csproj b/csharp/lib/Time/Time.csproj deleted file mode 100644 index a2a63460f..000000000 --- a/csharp/lib/Time/Time.csproj +++ /dev/null @@ -1,3 +0,0 @@ - - - From 1aec8e1fe97e1d1c31a3cc7a7eb10a49cba5d719 Mon Sep 17 00:00:00 2001 From: ig Date: Sat, 25 Feb 2023 16:16:12 +0100 Subject: [PATCH 012/114] Remove S3 lib --- csharp/InnovEnergy.props | 2 +- csharp/InnovEnergy.sln | 12 +- csharp/Lib/S3/DataRec.cs | 11 - .../Drivers/Internal/Delegates/ReadRecord.cs | 6 - .../Drivers/Internal/Delegates/WriteRecord.cs | 6 - csharp/Lib/S3/Drivers/Internal/Reader.cs | 50 ----- .../Lib/S3/Drivers/Internal/Reader.public.cs | 37 --- .../S3/Drivers/Internal/Util/Aggregator.cs | 60 ----- .../Lib/S3/Drivers/Internal/Util/Sampler.cs | 43 ---- csharp/Lib/S3/Drivers/Internal/Writer.cs | 129 ----------- .../Lib/S3/Drivers/Internal/Writer.public.cs | 26 --- csharp/Lib/S3/Drivers/MemoryDriver.cs | 57 ----- csharp/Lib/S3/Drivers/S3Config.cs | 83 ------- csharp/Lib/S3/Drivers/S3Driver.cs | 82 ------- csharp/Lib/S3/Metadata/AggregationLevel.cs | 52 ----- csharp/Lib/S3/Metadata/FieldType.cs | 8 - csharp/Lib/S3/Program.cs | 211 ------------------ csharp/Lib/S3/Records/Fields/Field.cs | 3 - csharp/Lib/S3/Records/Fields/NumberField.cs | 25 --- csharp/Lib/S3/Records/Fields/TextField.cs | 38 ---- csharp/Lib/S3/Records/Fields/TextFrequency.cs | 13 -- csharp/Lib/S3/Records/Fields/UnitAttribute.cs | 16 -- csharp/Lib/S3/Records/Fields/WithUnit.cs | 30 --- .../Lib/S3/Records/Operations/Aggregation.cs | 83 ------- .../Lib/S3/Records/Operations/Conversion.cs | 46 ---- csharp/Lib/S3/Records/Record.cs | 59 ----- .../Lib/S3/Records/Serialization/FieldTag.cs | 8 - csharp/Lib/S3/Records/Serialization/Parser.cs | 134 ----------- .../S3/Records/Serialization/Serializer.cs | 121 ---------- .../Records/Specialized/AggregatedRecord.cs | 23 -- .../Records/Specialized/TimeStampedRecord.cs | 27 --- csharp/Lib/S3/S3.csproj | 17 -- csharp/Lib/S3/Serialization/JsonConverters.cs | 167 -------------- csharp/Lib/SysTools/Edges/StringToCommand.cs | 28 +-- csharp/Lib/SysTools/FileIo.cs | 75 +++---- csharp/Lib/SysTools/Process/AsyncProcess.cs | 1 + csharp/Lib/SysTools/Process/ProcessResult.cs | 1 + csharp/Lib/SysTools/Process/SyncProcess.cs | 2 +- csharp/Lib/SysTools/Remote/RemoteCommand.cs | 1 + csharp/Lib/SysTools/Remote/RemoteFileIo.cs | 1 + csharp/Lib/SysTools/Remote/RemotePath.cs | 1 + csharp/Lib/SysTools/Remote/SshHost.cs | 1 + csharp/Lib/SysTools/SysCommand.cs | 1 + csharp/Lib/SysTools/SysDirs.cs | 1 + csharp/Lib/SysTools/SysPath.cs | 1 + csharp/Lib/SysTools/SysTools.csproj | 4 + csharp/Lib/SysTools/Utils/EnumerableUtils.cs | 34 +-- csharp/Lib/SysTools/Utils/Utils.cs | 50 ----- csharp/Lib/Utils/Utils.cs | 4 +- 49 files changed, 78 insertions(+), 1813 deletions(-) delete mode 100644 csharp/Lib/S3/DataRec.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Delegates/ReadRecord.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Delegates/WriteRecord.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Reader.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Reader.public.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Util/Aggregator.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Util/Sampler.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Writer.cs delete mode 100644 csharp/Lib/S3/Drivers/Internal/Writer.public.cs delete mode 100644 csharp/Lib/S3/Drivers/MemoryDriver.cs delete mode 100644 csharp/Lib/S3/Drivers/S3Config.cs delete mode 100644 csharp/Lib/S3/Drivers/S3Driver.cs delete mode 100644 csharp/Lib/S3/Metadata/AggregationLevel.cs delete mode 100644 csharp/Lib/S3/Metadata/FieldType.cs delete mode 100644 csharp/Lib/S3/Program.cs delete mode 100644 csharp/Lib/S3/Records/Fields/Field.cs delete mode 100644 csharp/Lib/S3/Records/Fields/NumberField.cs delete mode 100644 csharp/Lib/S3/Records/Fields/TextField.cs delete mode 100644 csharp/Lib/S3/Records/Fields/TextFrequency.cs delete mode 100644 csharp/Lib/S3/Records/Fields/UnitAttribute.cs delete mode 100644 csharp/Lib/S3/Records/Fields/WithUnit.cs delete mode 100644 csharp/Lib/S3/Records/Operations/Aggregation.cs delete mode 100644 csharp/Lib/S3/Records/Operations/Conversion.cs delete mode 100644 csharp/Lib/S3/Records/Record.cs delete mode 100644 csharp/Lib/S3/Records/Serialization/FieldTag.cs delete mode 100644 csharp/Lib/S3/Records/Serialization/Parser.cs delete mode 100644 csharp/Lib/S3/Records/Serialization/Serializer.cs delete mode 100644 csharp/Lib/S3/Records/Specialized/AggregatedRecord.cs delete mode 100644 csharp/Lib/S3/Records/Specialized/TimeStampedRecord.cs delete mode 100644 csharp/Lib/S3/S3.csproj delete mode 100644 csharp/Lib/S3/Serialization/JsonConverters.cs diff --git a/csharp/InnovEnergy.props b/csharp/InnovEnergy.props index c6c92bd2a..5a4943931 100644 --- a/csharp/InnovEnergy.props +++ b/csharp/InnovEnergy.props @@ -9,7 +9,7 @@ net6.0 true false - $(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("lib/", "Lib/").Replace("app/", "App/").Replace("src/", "").Replace("/",".")) + $(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("src/", "").Replace("/",".")) $(Company) Team diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 70c4b2f57..88f01a87d 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -20,10 +20,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{145597B4-3E3 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3", "Lib/S3/S3.csproj", "{C3639841-13F4-4F24-99C6-7D965593BF89}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deprecated", "deprecated", "{46DE03C4-52D1-47AA-8E60-8BB15361D723}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaliMax", "App/SaliMax/SaliMax.csproj", "{25073794-D859-4824-9984-194C7E928496}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusApi", "Lib/StatusApi/StatusApi.csproj", "{9D17E78C-8A70-43DB-A619-DC12D20D023D}" @@ -106,10 +102,6 @@ Global {40B45363-BE34-420B-8F87-775EE6EE3513}.Debug|Any CPU.Build.0 = Debug|Any CPU {40B45363-BE34-420B-8F87-775EE6EE3513}.Release|Any CPU.ActiveCfg = Release|Any CPU {40B45363-BE34-420B-8F87-775EE6EE3513}.Release|Any CPU.Build.0 = Release|Any CPU - {C3639841-13F4-4F24-99C6-7D965593BF89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C3639841-13F4-4F24-99C6-7D965593BF89}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C3639841-13F4-4F24-99C6-7D965593BF89}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C3639841-13F4-4F24-99C6-7D965593BF89}.Release|Any CPU.Build.0 = Release|Any CPU {25073794-D859-4824-9984-194C7E928496}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25073794-D859-4824-9984-194C7E928496}.Debug|Any CPU.Build.0 = Debug|Any CPU {25073794-D859-4824-9984-194C7E928496}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -187,11 +179,8 @@ Global {B2627B9F-41DF-44F7-A0D1-CA71FF4A007A} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {F65F33B0-3522-4008-8D1E-47EF8E4C7AC7} = {145597B4-3E30-45E6-9F72-4DD43194539A} {E3A5F3A3-72A5-47CC-85C6-2D8E962A0EC1} = {145597B4-3E30-45E6-9F72-4DD43194539A} - {46DE03C4-52D1-47AA-8E60-8BB15361D723} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} - {4A67D79F-F0C9-4BBC-9601-D5948E6C05D3} = {46DE03C4-52D1-47AA-8E60-8BB15361D723} {25073794-D859-4824-9984-194C7E928496} = {145597B4-3E30-45E6-9F72-4DD43194539A} {9D17E78C-8A70-43DB-A619-DC12D20D023D} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} - {C3639841-13F4-4F24-99C6-7D965593BF89} = {46DE03C4-52D1-47AA-8E60-8BB15361D723} {4931A385-24DC-4E78-BFF4-356F8D6D5183} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {794FD07C-93E9-4803-982E-1CA261504AB5} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {BD8CBC5C-0B9E-48A3-BC4E-725E3FAB2348} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} @@ -211,5 +200,6 @@ Global {AF7E8DCA-8D48-498E-AB3D-208061B244DC} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {A56F58C2-B265-435B-A985-53B4D6F49B1A} = {145597B4-3E30-45E6-9F72-4DD43194539A} {C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} + {4A67D79F-F0C9-4BBC-9601-D5948E6C05D3} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} EndGlobalSection EndGlobal diff --git a/csharp/Lib/S3/DataRec.cs b/csharp/Lib/S3/DataRec.cs deleted file mode 100644 index 5ae585689..000000000 --- a/csharp/Lib/S3/DataRec.cs +++ /dev/null @@ -1,11 +0,0 @@ -using InnovEnergy.Lib.S3.Records.Fields; - -namespace InnovEnergy.Lib.S3; - -public record DataRec -{ - [Unit("V")] public Double Voltage { get; init; } - [Unit("A")] public Double Current { get; init; } - public Boolean Error { get; init; } - public String State { get; init; } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Delegates/ReadRecord.cs b/csharp/Lib/S3/Drivers/Internal/Delegates/ReadRecord.cs deleted file mode 100644 index ad088d513..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Delegates/ReadRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records.Specialized; - -namespace InnovEnergy.Lib.S3.Drivers.Internal.Delegates; - -public delegate Task ReadRecord(AggregationLevel level, UInt32 index); \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Delegates/WriteRecord.cs b/csharp/Lib/S3/Drivers/Internal/Delegates/WriteRecord.cs deleted file mode 100644 index 4bccde97d..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Delegates/WriteRecord.cs +++ /dev/null @@ -1,6 +0,0 @@ -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records.Specialized; - -namespace InnovEnergy.Lib.S3.Drivers.Internal.Delegates; - -public delegate Task WriteRecord(TimeStampedRecord record, AggregationLevel level, UInt32 index); \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Reader.cs b/csharp/Lib/S3/Drivers/Internal/Reader.cs deleted file mode 100644 index e5ba5c59e..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Reader.cs +++ /dev/null @@ -1,50 +0,0 @@ -using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Drivers.Internal; - -public partial class Reader -{ - public IReadOnlyList AggregationLevels { get; } - public UnixTimeSpan SamplePeriod => AggregationLevels[0].SamplePeriod; - - private readonly ReadRecord _ReadRecord; - - internal Reader(IReadOnlyList levels, ReadRecord readRecord) - { - _ReadRecord = readRecord; - AggregationLevels = InitLevels(levels); - } - - public Task ReadRecord(AggregationLevel level, UInt32 index) - { - return _ReadRecord(level, index); - } - - private static IReadOnlyList InitLevels(IReadOnlyList levels) - { - if (!levels.Any()) - throw new ArgumentOutOfRangeException(nameof(levels)); - - levels = levels - .OrderBy(l => l.SamplePeriod.Ticks) - .ToReadOnlyList(levels.Count); - - var pairwise = levels - .Select(l => l.SamplePeriod) - .Pairwise() - .ToReadOnlyList(levels.Count - 1); - - var greater = pairwise.Any(ls => ls.right <= ls.left); - var multiple = pairwise.Any(ls => ls.right % ls.left != 0 ); - var retention = levels .Any(l => l.RetentionPeriod % l.SamplePeriod != 0); - - if (greater || multiple || retention) - throw new ArgumentException(nameof(levels)); // TODO: error messages - - return levels; - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Reader.public.cs b/csharp/Lib/S3/Drivers/Internal/Reader.public.cs deleted file mode 100644 index 424b3ccfe..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Reader.public.cs +++ /dev/null @@ -1,37 +0,0 @@ -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Drivers.Internal; - -public partial class Reader -{ - public Task> ReadRecords(UnixTime from, UnixTime to, Int32 minNumber) - { - var maxDt = (to - from) / minNumber; - return ReadRecords(from, to, maxDt); - } - - public async Task> ReadRecords(UnixTime from, UnixTime to, UnixTimeSpan maxDt) - { - if (maxDt < SamplePeriod) - maxDt = SamplePeriod; - - var level = AggregationLevels.LastOrDefault(l => l.SamplePeriod <= maxDt) ?? AggregationLevels[^1]; - - return await level - .RangeExclusive(from, to) - .Select(t => ReadRecord(level, t)) - .WhenAll(); - } - - public async Task ReadRecord(AggregationLevel level, UnixTime time) - { - var tsRecord = await ReadRecord(level, level.GetRetentionIndex(time)); - - return tsRecord.TimeStamp == time - ? tsRecord - : TimeStampedRecord.Empty(time); - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Util/Aggregator.cs b/csharp/Lib/S3/Drivers/Internal/Util/Aggregator.cs deleted file mode 100644 index 999a2aa1a..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Util/Aggregator.cs +++ /dev/null @@ -1,60 +0,0 @@ -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records; -using InnovEnergy.Lib.S3.Records.Operations; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Drivers.Internal.Util; - -public class Aggregator -{ - public AggregationLevel AggregationLevel { get; } - - private Record[] Buffer { get; } - private UInt32 Index { get; set; } - - public Aggregator(AggregationLevel thisLevel, - AggregationLevel levelBelow, - IEnumerable initialRecords) - { - var ratio = thisLevel.SamplePeriod / levelBelow.SamplePeriod; - - AggregationLevel = thisLevel; - - Index = 0; - Buffer = new Record[ratio]; - - Clear(); - - foreach (var record in initialRecords) - Aggregate(record); - } - - public Record? Aggregate(Record r) - { - Buffer[Index++] = r; - - return IsFull - ? ForceAggregation() - : null; - } - - public Record? ForceAggregation() - { - if (IsEmpty) - return null; // nothing to aggregate - - var aggregated = Buffer.Aggregate(); - Clear(); - return aggregated; - } - - private void Clear() - { - Buffer.Fill(Record.Empty); - Index = 0; - } - - private Boolean IsFull => Index == Buffer.Length; - private Boolean IsEmpty => Index == 0; - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Util/Sampler.cs b/csharp/Lib/S3/Drivers/Internal/Util/Sampler.cs deleted file mode 100644 index 384b00487..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Util/Sampler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; - -namespace InnovEnergy.Lib.S3.Drivers.Internal.Util; - -internal class Sampler -{ - public Record CurrentRecord { get; set; } - public UnixTime CurrentTimeStamp { get; set; } - public AggregationLevel AggregationLevel { get; } - - private UnixTimeSpan SamplePeriod => AggregationLevel.SamplePeriod; - - public Sampler(AggregationLevel aggregationLevel, Record record, UnixTime currentTime) - { - AggregationLevel = aggregationLevel; - CurrentRecord = record; - CurrentTimeStamp = aggregationLevel.GetPeriodStartTime(currentTime); - } - - - // TODO: repeat/max age - public IEnumerable Sample(Record record, UnixTime timeStamp) - { - timeStamp = AggregationLevel.GetPeriodStartTime(timeStamp); - - if (timeStamp < CurrentTimeStamp) - yield break; //throw new IndexOutOfRangeException(nameof(index)); // TODO: log - - if (timeStamp > CurrentTimeStamp) - yield return new AggregatedRecord(CurrentRecord, AggregationLevel, CurrentTimeStamp); - - for (var t = CurrentTimeStamp + SamplePeriod; t < timeStamp; t += SamplePeriod) - yield return new AggregatedRecord(Record.Empty, AggregationLevel, t); - - CurrentTimeStamp = timeStamp; - CurrentRecord = record; - } - - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Writer.cs b/csharp/Lib/S3/Drivers/Internal/Writer.cs deleted file mode 100644 index 19156a4d3..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Writer.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Diagnostics; -using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; -using InnovEnergy.Lib.S3.Drivers.Internal.Util; -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Drivers.Internal; - -using AggregationLevels = IReadOnlyList; -using Aggregators = IReadOnlyList; - -public partial class Writer : Reader, IDisposable -{ - private Sampler Sampler { get; } - private Aggregators Aggregators { get; } - - private readonly WriteRecord _WriteRecord; - - internal Writer(UnixTime startTime, - AggregationLevels levels, - ReadRecord readRecord, - WriteRecord writeRecord) : base(levels, readRecord) - { - _WriteRecord = writeRecord; - startTime = AggregationLevels.First().GetPeriodStartTime(startTime); - Sampler = InitializeSampler(startTime); - Aggregators = InitializeAggregators(startTime); - } - - private IReadOnlyList InitializeAggregators(UnixTime startTime) - { - return AggregationLevels - .Pairwise() - .SelectTuple((lo, hi) => InitializeAggregator(lo, hi, startTime)) - .ToReadOnlyList(AggregationLevels.Count - 1); - } - - private Aggregator InitializeAggregator(AggregationLevel lo, - AggregationLevel hi, - UnixTime currentTime) - { - // This was a REAL brainfuck to get right - - var loStartTime = lo.GetPeriodStartTime(currentTime); - var hiStartTime = hi.GetPeriodStartTime(currentTime); - - Debug.Assert(hiStartTime <= loStartTime); - - var initialRecords = lo - .RangeExclusive(hiStartTime, loStartTime) - .Select(t => ReadRecord(lo, t)) - .WhenAll() - .Result - .Select(r => r.Record); - - return new Aggregator(hi, lo, initialRecords); - } - - private Sampler InitializeSampler(UnixTime startTime) - { - var samplerLevel = AggregationLevels.First(); - var initialRecord = ReadRecord(samplerLevel, startTime).Result.Record; - - return new Sampler(samplerLevel, initialRecord, startTime); - } - - private IEnumerable Aggregate(Record record, UnixTime timeStamp) - { - return Sampler - .Sample(record, timeStamp) - .SelectMany(Aggregate); - } - - private IEnumerable Aggregate(AggregatedRecord r) - { - yield return r; - - var record = r.Record; - - foreach (var a in Aggregators) - { - record = a.Aggregate(record); - if (record is null) break; - - var timeStamp = a.AggregationLevel.GetPeriodStartTime(r.TimeStamp); - yield return new AggregatedRecord(record, a.AggregationLevel, timeStamp); - } - } - - private Task WriteRecord(AggregatedRecord rec) - { - var tsr = rec.ToTimeStamped(); - var level = rec.AggregationLevel; - var index = level.GetRetentionIndex(rec.TimeStamp); - - return _WriteRecord(tsr, level, index); - } - - void IDisposable.Dispose() - { - DisposeAsync().Wait(); - } - - private async Task DisposeAsync() - { - // feed the sampler an empty "next" record, so it writes and aggregates the current one. - await WriteRecord(Record.Empty, Sampler.CurrentTimeStamp + SamplePeriod); - - foreach (var a in Aggregators) - { - // force and write incomplete aggregation for each level - - var agg = a.ForceAggregation(); - if (agg is null) - continue; - - var lev = a.AggregationLevel; - var ts = lev.GetPeriodStartTime(Sampler.CurrentTimeStamp); - var tsr = agg!.TimeStamped(ts); - var idx = lev.GetRetentionIndex(ts); - - await _WriteRecord(tsr, lev, idx); - } - } - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/Internal/Writer.public.cs b/csharp/Lib/S3/Drivers/Internal/Writer.public.cs deleted file mode 100644 index 15ab491cf..000000000 --- a/csharp/Lib/S3/Drivers/Internal/Writer.public.cs +++ /dev/null @@ -1,26 +0,0 @@ -using InnovEnergy.Lib.S3.Records; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Drivers.Internal; - -public partial class Writer -{ - public Task WriteRecord(Record record) - { - return WriteRecord(record, UnixTime.Now); - } - - public Task WriteRecord(TimeStampedRecord tsr) - { - return WriteRecord(tsr.Record, tsr.TimeStamp); - } - - public Task WriteRecord(Record record, UnixTime time) - { - return Aggregate(record, time) - .Select(WriteRecord) - .WhenAll(); - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/MemoryDriver.cs b/csharp/Lib/S3/Drivers/MemoryDriver.cs deleted file mode 100644 index 8b70abf5e..000000000 --- a/csharp/Lib/S3/Drivers/MemoryDriver.cs +++ /dev/null @@ -1,57 +0,0 @@ -using InnovEnergy.Lib.S3.Drivers.Internal; -using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; - -namespace InnovEnergy.Lib.S3.Drivers; - -using Levels = IReadOnlyList; -using Memory = Dictionary; - -public class MemoryDriver : Writer -{ - - public MemoryDriver(Levels levels, UnixTime startTime, Memory memory) : - base( - startTime, - levels, - ReadRecord(memory), - WriteRecord(memory) - ) - { - } - - private static String GetKey(AggregationLevel level, UInt32 index) - { - return $"{level}/{index}"; - } - - private static ReadRecord ReadRecord(Memory memory) - { - Task Read(AggregationLevel level, UInt32 index) - { - var key = GetKey(level, index); - - var result = memory.TryGetValue(key, out var tsRecord) - ? tsRecord - : TimeStampedRecord.Empty(); - - return Task.FromResult(result); - } - - return Read; - } - - private static WriteRecord WriteRecord(Memory memory) - { - Task Write(TimeStampedRecord record, AggregationLevel level, UInt32 index) - { - var key = GetKey(level, index); - memory[key] = record; - return Task.CompletedTask; - } - - return Write; - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/S3Config.cs b/csharp/Lib/S3/Drivers/S3Config.cs deleted file mode 100644 index 758244b3f..000000000 --- a/csharp/Lib/S3/Drivers/S3Config.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Security.Cryptography; -using Flurl; -using Flurl.Http; -using InnovEnergy.Lib.Utils; -using static System.Text.Encoding; -using Convert = System.Convert; - -namespace InnovEnergy.Lib.S3.Drivers; - -public record S3Config -{ - public String Bucket { get; init; } = ""; - public String Region { get; init; } = ""; - public String Provider { get; init; } = ""; - public String Key { get; init; } = ""; - public String Secret { get; init; } = ""; - public String ContentType { get; init; } = ""; - - public String Host => $"{Bucket}.{Region}.{Provider}"; - public String Url => $"https://{Host}"; - - public IFlurlRequest CreatePutRequest(String s3Path) => CreateRequest("PUT", s3Path); - public IFlurlRequest CreateGetRequest(String s3Path) => CreateRequest("GET", s3Path); - - private IFlurlRequest CreateRequest(String method, String s3Path) - { - var date = DateTime.UtcNow.ToString("r"); - var auth = CreateAuthorization(method, s3Path, date); - - return Url - .AppendPathSegment(s3Path) - .WithHeader("Host", Host) - .WithHeader("Date", date) - .WithHeader("Authorization", auth) - .AllowAnyHttpStatus(); - } - - private String CreateAuthorization(String method, - String s3Path, - String date) - { - return CreateAuthorization - ( - method : method, - bucket : Bucket, - s3Path : s3Path, - date : date, - s3Key : Key, - s3Secret : Secret, - contentType: ContentType - ); - } - - - - private static String CreateAuthorization(String method, - String bucket, - String s3Path, - String date, - String s3Key, - String s3Secret, - String contentType = "", - String md5Hash = "") - { - // StringToSign = HTTP-Verb + "\n" + - // Content-MD5 + "\n" + - // Content-Type + "\n" + - // Date + "\n" + - // CanonicalizedAmzHeaders + - // CanonicalizedResource; - - var payload = $"{method}\n{md5Hash}\n{contentType}\n{date}\n/{bucket.Trim('/')}/{s3Path.Trim('/')}"; - using var hmacSha1 = new HMACSHA1(UTF8.GetBytes(s3Secret)); - - var signature = UTF8 - .GetBytes(payload) - .Apply(hmacSha1.ComputeHash) - .Apply(Convert.ToBase64String); - - return $"AWS {s3Key}:{signature}"; - } - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Drivers/S3Driver.cs b/csharp/Lib/S3/Drivers/S3Driver.cs deleted file mode 100644 index 9d231e998..000000000 --- a/csharp/Lib/S3/Drivers/S3Driver.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Flurl.Http; -using InnovEnergy.Lib.S3.Drivers.Internal; -using InnovEnergy.Lib.S3.Drivers.Internal.Delegates; -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.S3.Records.Serialization; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; - -namespace InnovEnergy.Lib.S3.Drivers; - -using Levels = IReadOnlyList; - -public class S3Driver : Writer -{ - - public S3Driver(Levels levels, UnixTime startTime, S3Config config) : - base( - startTime, - levels, - ReadRecord(config), - WriteRecord(config) - ) - { - } - - private static String GetS3Path(AggregationLevel level, UInt32 index) - { - return $"/{level}/{index}"; - } - - private static ReadRecord ReadRecord(S3Config config) - { - async Task Read(AggregationLevel level, UInt32 index) - { - var s3Path = GetS3Path(level, index); - var request = config.CreateGetRequest(s3Path); - var response = await request.GetAsync(); - - if (response.StatusCode != 200) - { - Console.WriteLine("ERROR: Get " + s3Path); - var error = await response.GetStringAsync(); - Console.WriteLine(error); - return TimeStampedRecord.Empty(); - } - - var payload = await response.GetBytesAsync(); - - Console.WriteLine("GET " + s3Path); - return Parser.ParseTimeStampedRecord(payload); - } - - return Read; - } - - private static WriteRecord WriteRecord(S3Config config) - { - async Task Write(TimeStampedRecord record, AggregationLevel level, UInt32 index) - { - var payload = record.Serialize().ToArray(); - var s3Path = GetS3Path(level, index); - var request = config.CreatePutRequest(s3Path); - var response = await request.PutAsync(new ByteArrayContent(payload)); - - if (response.StatusCode == 200) - { - //Console.WriteLine("PUT " + s3Path); - } - else - { - Console.WriteLine("ERROR: PUT"); - var error = await response.GetStringAsync(); - Console.WriteLine(error); - } - } - - return Write; - } - - - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Metadata/AggregationLevel.cs b/csharp/Lib/S3/Metadata/AggregationLevel.cs deleted file mode 100644 index fd1ecd184..000000000 --- a/csharp/Lib/S3/Metadata/AggregationLevel.cs +++ /dev/null @@ -1,52 +0,0 @@ -using InnovEnergy.Lib.Time.Unix; - -namespace InnovEnergy.Lib.S3.Metadata; - -public record AggregationLevel -{ - public UnixTimeSpan RetentionPeriod { get; } - public UnixTimeSpan SamplePeriod { get; } - public UInt32 RetentionBufferSize { get; } - - public AggregationLevel(UnixTimeSpan samplePeriod, UnixTimeSpan retentionPeriod) - { - SamplePeriod = samplePeriod; - RetentionPeriod = retentionPeriod; - RetentionBufferSize = retentionPeriod / samplePeriod; - } - - public IEnumerable RangeExclusive(UnixTime from, UnixTime to) - { - if (from > to) - throw new ArgumentOutOfRangeException(nameof(to)); - - for (var t = GetPeriodStartTime(from); t < to; t += SamplePeriod) - yield return t; - } - - - // TODO: - public IEnumerable RangeInclusive(UnixTime from, UnixTime to) - { - if (from >= to) - throw new ArgumentOutOfRangeException(nameof(to)); - - from = GetPeriodStartTime(from); - to = GetPeriodStartTime(to) + SamplePeriod; - - for (var t = GetPeriodStartTime(from); t < to; t += SamplePeriod) - yield return t; - } - - public UInt32 GetRetentionIndex(UnixTime t) - { - return t / SamplePeriod % RetentionBufferSize; - } - - public UnixTime GetPeriodStartTime(UnixTime t) - { - return UnixTime.Epoch + t / SamplePeriod * SamplePeriod; // integer division! - } - - public override String ToString() => SamplePeriod.ToString(); -} \ No newline at end of file diff --git a/csharp/Lib/S3/Metadata/FieldType.cs b/csharp/Lib/S3/Metadata/FieldType.cs deleted file mode 100644 index 9ca91a1af..000000000 --- a/csharp/Lib/S3/Metadata/FieldType.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace InnovEnergy.Lib.S3.Metadata; - -public enum FieldType -{ - Number, - Text, - Boolean, -} \ No newline at end of file diff --git a/csharp/Lib/S3/Program.cs b/csharp/Lib/S3/Program.cs deleted file mode 100644 index 4ba261f71..000000000 --- a/csharp/Lib/S3/Program.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System.Reactive.Concurrency; -using System.Reactive.Linq; -using System.Reactive.Subjects; -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.Time.Unix; -using InnovEnergy.Lib.Utils; -using static InnovEnergy.Lib.Time.Unix.UnixTimeSpan; - -namespace InnovEnergy.Lib.S3; - - - -public enum MyEnum -{ - Foo = 0x01, - Bar = 0x02, - Baz = 0x04 -} - - -public record Test(Double X, Double Y, Double Z); - - - - -public static class Program -{ - private static readonly Random Rng = new Random(0); - - - - - - - public static void Main(String[] args) - { - - // var x = Observable - // .Range(0, 22) - // .Select(i=> new Dictionary - // { - // {"i", i}, - // {"i*2", i * 2}, - // {"i/2", i / 2}, - // }) - // .DictObserve(o => Observable.Where(o, i=> i < 10)); - // - // x.Subscribe(ints => Console.WriteLine(String.Join(Environment.NewLine,ints) + "\n") ); - - - var src = Observable - .Interval(TimeSpan.FromSeconds(1)) - .BufferBy(i => i / 5) - .Subscribe(b => - { - var values = b.Select(e => e.ToString()).Aggregate("", (x, y) => $"{x}\n{y}"); - var average = b.Average(); - var msg = $"{values}\nAverage: {average}"; - - Console.WriteLine(msg); - }); - - - - Console.ReadLine(); - // var t = new Test(12, 2, 1); - // - // foreach (var m in typeof(Test).GetMembers().OfType()) - // { - // var parameters = m - // .GetParameters() - // .Select(p => $"{p.ParameterType.Name} {p.Name}") - // .Aggregate("", (a, b) => a + ", " + b) - // .TrimStart(", ".ToCharArray()); - // - // Console.WriteLine($"{m.ReturnType.Name} {m.Name}({parameters})"); - // } - - - return; - - var s = new Subject(); - - Observable.Interval(TimeSpan.FromSeconds(2), TaskPoolScheduler.Default) - .WithLatestFrom(s, (_, x) => x) - .Subscribe(Console.WriteLine); - - while (true) - { - var k = Console.ReadKey(true); - s.OnNext(k.KeyChar.ToString()); - } - - - - - var levels = new [] - { - new AggregationLevel( 2.Seconds(), 54.Weeks()), - new AggregationLevel(10.Seconds(), 54.Weeks()), - new AggregationLevel( 1.Minutes(), 54.Weeks()), - new AggregationLevel( 5.Minutes(), 540.Weeks()), - new AggregationLevel(15.Minutes(), 540.Weeks()), - new AggregationLevel( 1.Hours() , 540.Weeks()), - new AggregationLevel( 6.Hours() , 540.Weeks()), - new AggregationLevel( 1.Days() , 540.Weeks()), - new AggregationLevel( 1.Weeks() , Forever) - }; - - var resolution = 2.Seconds(); - - for (int i = 0; i < 10; i++) - { - var startTime = UnixTime.Epoch + Rng.Next(0, 2.Weeks().Ticks.ConvertTo()).Seconds(); - var split = Rng.Next(2, 1000); - - //Test(startTime, resolution, levels, split); - } - - - Console.WriteLine("Done"); - } - - // private static void Test(UnixTime startTime, UnixTimeSpan resolution, AggregationLevel[] aggregationLevels, Int32 split) - // { - // var times = Enumerable - // .Range(0, 2.Weeks().Ticks.ConvertTo()) - // .Select(t => startTime + t * resolution) - // .ToReadOnlyList(); - // - // var records = times - // //.Where(_ => Rng.NextDouble() > .25) // "loose" 1 in 4 - // .Select(t => ( - // record: new Record - // ( - // // new NumberField("Current", t.Ticks / 2, "A"), - // new SubRecord("Sub1", new Record(new NumberField("Current1", t.Ticks / 4, "A"))), - // new SubRecord("Sub2", new Record(new NumberField("Current2", t.Ticks / 8, "A"))) - // ), - // time: t + Rng.NextDouble().Apply(Math.Round).ConvertTo().Seconds() // add noise - // )) - // .ToList(); - // - // - // var allMemory = new Dictionary(); - // using (var driverAll = new MemoryDriver(aggregationLevels, startTime, allMemory)) - // { - // foreach (var record in records) - // driverAll.WriteRecord(record.record, record.time); - // } - // - // var list = allMemory.Where(kv => kv.Key.StartsWith("1w")).ToList(); - // - // var splitMemory = new Dictionary(); - // using (var driver1 = new MemoryDriver(aggregationLevels, startTime, splitMemory)) - // { - // foreach (var record in records.Take(split)) - // driver1.WriteRecord(record.record, record.time); - // } - // - // using (var driver2 = new MemoryDriver(aggregationLevels, records.ElementAt(split-1).time, splitMemory)) - // { - // foreach (var record in records.Skip(split-1)) - // driver2.WriteRecord(record.record, record.time); - // } - // - // - // - // var zip = Enumerable.Zip( - // allMemory.OrderBy(kv => kv.Key), - // splitMemory.OrderBy(kv => kv.Key) - // ); - // - // foreach (var (l, r) in zip) - // { - // var nl = l.Value.Record.Fields.OfType().FirstOrDefault()?.Value; - // var nr = r.Value.Record.Fields.OfType().FirstOrDefault()?.Value; - // - // if (l.Key != r.Key) - // { - // Console.WriteLine($"{l.Key} <=> {r.Key}"); - // break; - // } - // - // if (nl != nr) - // { - // Console.WriteLine($"{l.Value.TimeStamp.ToUtcDateTime()}: {nl} <=> {nr}"); - // } - // } - // } - - - public static String CreateRandomState() - { - var r = Rng.NextDouble() * 100; - - return r switch - { - >= 90 => "Heating", - >= 10 => "SelfConsumption", - _ => "CalibrationCharge" - }; - } - - - - - - - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Fields/Field.cs b/csharp/Lib/S3/Records/Fields/Field.cs deleted file mode 100644 index a68f29cd4..000000000 --- a/csharp/Lib/S3/Records/Fields/Field.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace InnovEnergy.Lib.S3.Records.Fields; - -public abstract record Field; \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Fields/NumberField.cs b/csharp/Lib/S3/Records/Fields/NumberField.cs deleted file mode 100644 index 62aca9f6c..000000000 --- a/csharp/Lib/S3/Records/Fields/NumberField.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace InnovEnergy.Lib.S3.Records.Fields; - -public record NumberField : Field -{ - public Double Value { get; } - public Double Min { get; } - public Double Max { get; } - public String Unit { get; } - - public NumberField(Double value, Double min, Double max, String unit = "") - { - Value = value; - Min = min; - Max = max; - Unit = unit; - } - - public NumberField(Double value, String unit = "") : this(value, value, value, unit) - { - } - - public NumberField(Boolean value) : this(value?100:0, "%") - { - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Fields/TextField.cs b/csharp/Lib/S3/Records/Fields/TextField.cs deleted file mode 100644 index 7b1ebd2e4..000000000 --- a/csharp/Lib/S3/Records/Fields/TextField.cs +++ /dev/null @@ -1,38 +0,0 @@ -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Records.Fields; - -public record TextField : Field -{ - public IReadOnlyList Frequencies { get; } - - public TextField(IReadOnlyList frequencies) - { - Frequencies = frequencies; - } - - public TextField(params TextFrequency[] frequencies) : this((IReadOnlyList)frequencies) - { - } - - public TextField(String text) : this(new TextFrequency(text)) - { - } - - public TextField(Enum enumValue) : this(GetEnumFlagsAsFrequencies(enumValue)) - { - } - - private static IReadOnlyList GetEnumFlagsAsFrequencies(Enum enumValue) - { - return enumValue - .ToString() - .Split(',') // debug view is '|' separated, toString() uses ',' !! - .Select(v => v.Trim()) - .Where(v => !v.IsInteger()) // filter "unknown" enum flags - .Select(f => new TextFrequency(f)) - .ToReadOnlyList(); - } - - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Fields/TextFrequency.cs b/csharp/Lib/S3/Records/Fields/TextFrequency.cs deleted file mode 100644 index 60974957f..000000000 --- a/csharp/Lib/S3/Records/Fields/TextFrequency.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace InnovEnergy.Lib.S3.Records.Fields; - -public record TextFrequency -{ - public TextFrequency(String text, Double percent = 100) - { - Text = text; - Percent = percent; - } - - public String Text { get; } - public Double Percent { get; } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Fields/UnitAttribute.cs b/csharp/Lib/S3/Records/Fields/UnitAttribute.cs deleted file mode 100644 index 1bd25600c..000000000 --- a/csharp/Lib/S3/Records/Fields/UnitAttribute.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace InnovEnergy.Lib.S3.Records.Fields; - -[AttributeUsage(AttributeTargets.Property)] -public sealed class UnitAttribute : Attribute -{ - private readonly String _Unit; - - public UnitAttribute(String unit) - { - _Unit = unit; - } - - public override String ToString() => _Unit; - - public static implicit operator String(UnitAttribute a) => a.ToString(); -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Fields/WithUnit.cs b/csharp/Lib/S3/Records/Fields/WithUnit.cs deleted file mode 100644 index 01104d9de..000000000 --- a/csharp/Lib/S3/Records/Fields/WithUnit.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace InnovEnergy.Lib.S3.Records.Fields; - -public readonly struct WithUnit -{ - public String Unit { get; } - public Double Value { get; } - - public WithUnit(Double value, String unit) - { - Unit = unit; - Value = value; - } - - public override String ToString() => Unit; -} - -public static class UnitExtensions -{ - public static WithUnit Unit(this Double number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this Single number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this Half number, String unit) => new WithUnit((Double) number, unit); - public static WithUnit Unit(this SByte number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this Byte number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this Int16 number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this UInt16 number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this Int32 number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this UInt32 number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this Int64 number, String unit) => new WithUnit(number, unit); - public static WithUnit Unit(this UInt64 number, String unit) => new WithUnit(number, unit); -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Operations/Aggregation.cs b/csharp/Lib/S3/Records/Operations/Aggregation.cs deleted file mode 100644 index 1b938947f..000000000 --- a/csharp/Lib/S3/Records/Operations/Aggregation.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using InnovEnergy.Lib.S3.Records.Fields; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Records.Operations; - -// ReSharper disable ArgumentsStyleOther - - -public static class Aggregation -{ - - [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] - public static Record Aggregate(this IReadOnlyList records) - { - var availability = records.Sum(r => r.Availability) / records.Count; - - if (availability == 0) - return Record.Empty; - - var numbers = records.GetColumns().Select(AggregateNumbers); - var texts = records.GetColumns() .Select(AggregateTexts); - var subRecords = records.GetColumns() .Select(AggregateRecords); - - var aggregated = numbers.Concat(texts).Concat(subRecords); - - var fields = new Dictionary(aggregated); - - return new Record - ( - fields, - availability - ); - } - - private static IEnumerable<(String name, F field)> GetFields(this IEnumerable records) where F : Field - { - foreach (var record in records) - foreach (var (name, field) in record.Fields) - if (field is F f) - yield return (name, f); - } - - private static ILookup GetColumns(this IEnumerable records) where F : Field - { - return records - .GetFields() - .ToLookup(nf => nf.name, nf => nf.field); - } - - - private static KeyValuePair AggregateTexts(IGrouping column) - { - var textFrequencies = column - .SelectMany(s => s.Frequencies) - .GroupBy(f => f.Text, f => f.Percent) - .Select(g => new TextFrequency(text: g.Key, percent: g.Sum() / g.Count())) - .OrderBy(f => f.Text) - .ToReadOnlyList(); - - return new (column.Key, new TextField(textFrequencies)); - } - - private static KeyValuePair AggregateNumbers(IGrouping column) - { - var aggregated = new NumberField - ( - min: column.Min(f => f.Min), - max: column.Max(f => f.Max), - value: column.Average(f => f.Value), - unit: column.First().Unit - ); - - return new (column.Key, aggregated); - } - - private static KeyValuePair AggregateRecords(IGrouping column) - { - var aggregate = column.ToReadOnlyList().Apply(Aggregate); - - return new(column.Key, aggregate); - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Operations/Conversion.cs b/csharp/Lib/S3/Records/Operations/Conversion.cs deleted file mode 100644 index cb68eb4ca..000000000 --- a/csharp/Lib/S3/Records/Operations/Conversion.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Reflection; -using InnovEnergy.Lib.S3.Records.Fields; -using InnovEnergy.Lib.Utils; -using static System.Reflection.BindingFlags; - -namespace InnovEnergy.Lib.S3.Records.Operations; - -public static class Conversion -{ - public static Record ToRecord(this Object t) - { - var fields = t.GetType() - .Apply(GetProperties) - .ToDictionary(p => p.Name, PropertyToField); - - return new Record(fields); - - Field PropertyToField(PropertyInfo p) => p.GetValue(t) switch - { - Double d => new NumberField(d, Unit(p)), - Boolean b => new NumberField(b), - Enum e => new TextField(e), - String s => new TextField(s), // ReSharper disable once PatternAlwaysOfType - Object o => ToRecord(o), - _ => throw new ArgumentException() - }; - } - - private static String Unit(MemberInfo member) - { - return member - .GetCustomAttributes() - .OfType() - .FirstOrDefault()? - .ToString() - ?? ""; - } - - private static IEnumerable GetProperties() => typeof(T).GetProperties(Instance | Public); - - private static IEnumerable GetProperties(Type t) => t.GetProperties(Instance | Public); - - - - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Record.cs b/csharp/Lib/S3/Records/Record.cs deleted file mode 100644 index 365765843..000000000 --- a/csharp/Lib/S3/Records/Record.cs +++ /dev/null @@ -1,59 +0,0 @@ -using InnovEnergy.Lib.S3.Records.Fields; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; - -namespace InnovEnergy.Lib.S3.Records; - -public record Record : Field -{ - public static Record Empty { get; } = new Record(new Dictionary(), 0); - - public IReadOnlyDictionary Fields { get; } - public Double Availability { get; } - - public Boolean IsEmpty => Fields.Count == 0; - - - public Record(IReadOnlyDictionary fields, Double availability = 1.0) - { - Fields = fields; - Availability = availability; - } - - public F GetField(String name) where F : Field - { - return (F) Fields[name]; - } - - public TimeStampedRecord TimeStamped(UnixTime unixTime) => new TimeStampedRecord(this, unixTime); - - - public static Record ParseDict(Dictionary dict, Double availability = 1.0) - { - var fields = dict.ToDictionary(kv => kv.Key, kv => ParseField(kv.Value)); - return new Record(fields, availability); - } - - private static Field ParseField(Object value) => - value switch - { - WithUnit v => new NumberField(v.Value, v.Unit), - Enum v => new TextField(v), - String v => new TextField(v), - Double v => new NumberField(v), - Field v => v, - Single v => new NumberField(v), - SByte v => new NumberField(v), - Byte v => new NumberField(v), - Int16 v => new NumberField(v), - UInt16 v => new NumberField(v), - Int32 v => new NumberField(v), - UInt32 v => new NumberField(v), - Int64 v => new NumberField(v), - UInt64 v => new NumberField(v), - Half v => new NumberField((Double)v), - _ => throw new ArgumentOutOfRangeException(nameof(value)) - }; - - -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Serialization/FieldTag.cs b/csharp/Lib/S3/Records/Serialization/FieldTag.cs deleted file mode 100644 index 8dff3261b..000000000 --- a/csharp/Lib/S3/Records/Serialization/FieldTag.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace InnovEnergy.Lib.S3.Records.Serialization; - -public enum FieldTag : Byte -{ - NumberField = 0, - TextField = 1, - RecordField = 2, -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Serialization/Parser.cs b/csharp/Lib/S3/Records/Serialization/Parser.cs deleted file mode 100644 index 76319a31a..000000000 --- a/csharp/Lib/S3/Records/Serialization/Parser.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System.Text; -using InnovEnergy.Lib.S3.Records.Fields; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.S3.Records.Serialization; - -public class Parser -{ - private Int32 Position { get; set; } - private Byte[] Data { get; } - - private Parser(Byte[] data, Int32 position = 0) - { - Data = data; - Position = position; - } - - public Boolean IsPastEnd => Position >= Data.Length; - - public static TimeStampedRecord ParseTimeStampedRecord(Byte[] data) - { - var parser = new Parser(data); - - var timeStamp = parser.ParseUnixTime(); - var record = parser.ParseRecord(); - - return new TimeStampedRecord(record, timeStamp); - } - - - private UnixTime ParseUnixTime() - { - var span = new ReadOnlySpan(Data, Position, sizeof(UInt32)); - var ticks = BitConverter.ToUInt32(span); - - Position += span.Length; - - return UnixTime.FromTicks(ticks); - } - - private Single ParseFloat() - { - var span = new ReadOnlySpan(Data, Position, sizeof(Single)); - Position += span.Length; - return BitConverter.ToSingle(span); - } - - private String ParseString() - { - var len = GetByte(); - var span = new ReadOnlySpan(Data, Position, len); - - Position += span.Length; - - return Encoding.UTF8.GetString(span); - } - - private NumberField ParseNumberField() - { - var value = ParseFloat(); - var min = ParseFloat(); - var max = ParseFloat(); - var unit = ParseString(); - - return new NumberField(value, min, max, unit); - } - - private TextFrequency ParseTextFrequency() - { - var txt = ParseString(); - var frq = ParseFloat(); - - return new TextFrequency(txt, frq); - } - - private Record ParseRecord() - { - var availability = ParseFloat(); - var fields = ParseFields(); - - return new Record(fields, availability); - } - - private IReadOnlyDictionary ParseFields() - { - var len = GetByte(); - - var fields = Enumerable - .Range(0, len) - .Select(_ => ParseNamedField()); - - return new Dictionary(fields); - } - - private Field ParseField() - { - var tag = ParseFieldTag(); - - return tag switch - { - FieldTag.NumberField => ParseNumberField(), - FieldTag.TextField => ParseTextField(), - FieldTag.RecordField => ParseRecord(), - _ => throw new ArgumentOutOfRangeException(nameof(FieldTag)) - }; - } - - private KeyValuePair ParseNamedField() - { - var name = ParseString(); - var field = ParseField(); - - return new KeyValuePair(name, field); - } - - - private TextField ParseTextField() - { - var len = GetByte(); - - var fqs = Enumerable - .Range(0, len) - .Select(_ => ParseTextFrequency()) - .ToReadOnlyList(len); - - return new TextField(fqs); - } - - private Byte GetByte() => Data[Position++]; - - private FieldTag ParseFieldTag() => (FieldTag) GetByte(); -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Serialization/Serializer.cs b/csharp/Lib/S3/Records/Serialization/Serializer.cs deleted file mode 100644 index d7766df8d..000000000 --- a/csharp/Lib/S3/Records/Serialization/Serializer.cs +++ /dev/null @@ -1,121 +0,0 @@ -using InnovEnergy.Lib.S3.Records.Fields; -using InnovEnergy.Lib.S3.Records.Specialized; -using InnovEnergy.Lib.Time.Unix; -using InnovEnergy.Lib.Utils; -using static System.Text.Encoding; - -namespace InnovEnergy.Lib.S3.Records.Serialization; - -public static class Serializer -{ - public static IEnumerable Serialize(this TimeStampedRecord tsr) - { - if (!BitConverter.IsLittleEndian) - throw new ArgumentException(nameof(BitConverter)); - - var timeStamp = tsr.TimeStamp.Serialize(); - var record = tsr.Record.Serialize(); - return timeStamp.Concat(record); - } - - private static IEnumerable Serialize(this UnixTime t) - { - return BitConverter.GetBytes(t.Ticks); - } - - private static IEnumerable Serialize(this Record r) - { - var availability = r.Availability.Serialize(); - var fields = r.Fields.Serialize(); - - return availability.Concat(fields); - } - - private static IEnumerable Serialize(this IReadOnlyDictionary fields) - { - var len = fields.GetLength(); - - return fields - .SelectMany(Serialize) - .Prepend(len); - } - - private static IEnumerable Serialize(this KeyValuePair kv) - { - var name = kv.Key.Serialize(); - var field = kv.Value.Serialize(); - - return name.Concat(field); - } - - - public static IEnumerable Serialize(this Field f) - { - return f switch - { - NumberField nf => Serialize(nf).PrependTag(FieldTag.NumberField), - TextField tf => Serialize(tf).PrependTag(FieldTag.TextField), - Record r => Serialize(r).PrependTag(FieldTag.RecordField), - _ => throw new ArgumentException(nameof(f)) - }; - } - - public static IEnumerable Serialize(NumberField nf) - { - var value = nf.Value.Serialize(); - var min = nf.Min .Serialize(); - var max = nf.Max .Serialize(); - var unit = nf.Unit .Serialize(); - - return value - .Concat(min) - .Concat(max) - .Concat(unit); - } - - public static IEnumerable Serialize(this TextField tf) - { - var len = tf.Frequencies.GetLength(); - return tf - .Frequencies - .SelectMany(Serialize) - .Prepend(len); - } - - public static IEnumerable Serialize(this TextFrequency tf) - { - var txt = tf.Text.Serialize(); - var frq = tf.Percent.Serialize(); - - return txt.Concat(frq); - } - - public static IEnumerable Serialize(this Double d) - { - return BitConverter.GetBytes((Single) d); // use float to save space - } - - - public static IEnumerable Serialize(this String s) - { - return UTF8 - .GetBytes(s) - .Apply(PrependLength); - } - - private static IEnumerable PrependTag(this IEnumerable data, FieldTag fieldTag) - { - return data.Prepend((Byte) fieldTag); - } - - private static IEnumerable PrependLength(IReadOnlyCollection data) - { - var len = (Byte) data.Count; - return data.Prepend(len); - } - - private static Byte GetLength(this IReadOnlyCollection data) - { - return (Byte) data.Count; - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Specialized/AggregatedRecord.cs b/csharp/Lib/S3/Records/Specialized/AggregatedRecord.cs deleted file mode 100644 index e4b9a2283..000000000 --- a/csharp/Lib/S3/Records/Specialized/AggregatedRecord.cs +++ /dev/null @@ -1,23 +0,0 @@ -using InnovEnergy.Lib.S3.Metadata; -using InnovEnergy.Lib.Time.Unix; - -namespace InnovEnergy.Lib.S3.Records.Specialized; - -public readonly struct AggregatedRecord -{ - public UnixTime TimeStamp { get; } - public Record Record { get; } - public AggregationLevel AggregationLevel { get; } - - public AggregatedRecord(Record record, AggregationLevel level, UnixTime timeStamp) - { - AggregationLevel = level; - TimeStamp = timeStamp; - Record = record; - } - - public TimeStampedRecord ToTimeStamped() - { - return new TimeStampedRecord(Record, TimeStamp); - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/Records/Specialized/TimeStampedRecord.cs b/csharp/Lib/S3/Records/Specialized/TimeStampedRecord.cs deleted file mode 100644 index 57dc56aed..000000000 --- a/csharp/Lib/S3/Records/Specialized/TimeStampedRecord.cs +++ /dev/null @@ -1,27 +0,0 @@ -using InnovEnergy.Lib.Time.Unix; - -namespace InnovEnergy.Lib.S3.Records.Specialized; - -public readonly struct TimeStampedRecord -{ - public UnixTime TimeStamp { get; } - public Record Record { get; } - - public TimeStampedRecord(Record record, UnixTime timeStamp) - { - Record = record; - TimeStamp = timeStamp; - } - - public Boolean IsEmpty => Record.IsEmpty; - - public static TimeStampedRecord Empty() - { - return Empty(UnixTime.Epoch); - } - - public static TimeStampedRecord Empty(UnixTime timeStamp) - { - return new TimeStampedRecord(Record.Empty, timeStamp); - } -} \ No newline at end of file diff --git a/csharp/Lib/S3/S3.csproj b/csharp/Lib/S3/S3.csproj deleted file mode 100644 index 946c4841f..000000000 --- a/csharp/Lib/S3/S3.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/csharp/Lib/S3/Serialization/JsonConverters.cs b/csharp/Lib/S3/Serialization/JsonConverters.cs deleted file mode 100644 index aa2de6bb2..000000000 --- a/csharp/Lib/S3/Serialization/JsonConverters.cs +++ /dev/null @@ -1,167 +0,0 @@ -// using System; -// using System.Text.Json; -// using System.Text.Json.Serialization; -// using InnovEnergy.S3.Records; -// using InnovEnergy.S3.Records.Fields; -// -// namespace InnovEnergy.S3.Serialization -// { -// public class SubClassConverterFactory : JsonConverterFactory -// { -// public override Boolean CanConvert(Type t) -// { -// return t.IsAbstract && t.IsClass; -// } -// -// public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) -// { -// var converterType = typeof(SubClassConverter<>).MakeGenericType(type); -// return (JsonConverter) Activator.CreateInstance(converterType)!; -// } -// -// public class SubClassConverter : JsonConverter -// { -// public override Boolean CanConvert(Type type) -// { -// return type == typeof(T); -// } -// -// public override T Read(ref Utf8JsonReader r, Type t, JsonSerializerOptions o) -// { -// throw new NotImplementedException(); -// } -// -// public override void Write(Utf8JsonWriter writer, T obj, JsonSerializerOptions options) -// { -// JsonSerializer.Serialize(writer, obj, obj!.GetType()); -// } -// } -// } -// -// public class DataRecordConverter : JsonConverter -// { -// public override Boolean CanConvert(Type type) -// { -// return typeof(Record).IsAssignableFrom(type); -// } -// -// public override Record Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) -// { -// throw new NotImplementedException(); -// } -// -// public override void Write(Utf8JsonWriter writer, Record @record, JsonSerializerOptions options) -// { -// writer.WriteStartObject(); -// -// foreach (var field in record.Fields) -// { -// writer.WritePropertyName(field.Name); -// -// if (field is NumberField an) -// { -// writer.WriteStartObject(); -// writer.WriteNumber("Min", an.Min); -// writer.WriteNumber("Max", an.Max); -// writer.WriteNumber("Mean", an.Value); -// writer.WriteEndObject(); -// } -// else if (field is TextField at) -// { -// writer.WriteStartObject(); -// foreach (var f in at.Frequencies) -// { -// writer.WriteNumber(f.Text, f.Percent); -// } -// writer.WriteEndObject(); -// } -// else if (field is BooleanField ab) -// { -// writer.WriteStartObject(); -// writer.WriteNumber("PercentTrue", ab.PercentTrue); -// writer.WriteEndObject(); -// } -// else -// throw new NotSupportedException(); -// } -// -// writer.WriteNumber("Time", record.TimeStamp.Ticks); -// writer.WriteNumber("Availability", record.Availability); -// -// writer.WriteEndObject(); -// } -// } -// -// // public class AggregatedRecordConverter : JsonConverter -// // { -// // public override Boolean CanConvert(Type type) -// // { -// // return typeof(AggregatedRecord).IsAssignableFrom(type); -// // } -// // -// // public override AggregatedRecord Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException(); -// // -// // public override void Write(Utf8JsonWriter writer, AggregatedRecord dataRecord, JsonSerializerOptions options) -// // { -// // writer.WriteStartObject(); -// // -// // foreach (var field in dataRecord.Fields) -// // { -// // if (field is AggregatedNumber n) -// // { -// // writer.WritePropertyName(n.Name); -// // writer.WriteStartObject(); -// // writer.WritePropertyName("Mean"); -// // writer.WriteNumberValue(n.Mean); -// // -// // writer.WritePropertyName("Min"); -// // writer.WriteNumberValue(n.Min); -// // -// // writer.WritePropertyName("Max"); -// // writer.WriteNumberValue(n.Max); -// // -// // writer.WriteEndObject(); -// // } -// // else if (field is AggregatedText t) -// // { -// // writer.WritePropertyName(t.Name); -// // JsonSerializer.Serialize(writer, t); -// // } -// // else if (field is AggregatedBoolean b) -// // { -// // writer.WritePropertyName(b.Name); -// // JsonSerializer.Serialize(writer, b); -// // } -// // -// // else throw new NotSupportedException(); -// // } -// // -// // writer.WriteEndObject(); -// // } -// // -// // -// // -// // -// // } -// -// // public class TextFrequencyConverter : JsonConverter -// // { -// // public override Boolean CanConvert(Type type) -// // { -// // return typeof(TextFrequency).IsAssignableFrom(type); -// // } -// // -// // public override TextFrequency Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException(); -// // -// // public override void Write(Utf8JsonWriter writer, TextFrequency textFrequency, JsonSerializerOptions options) -// // { -// // writer.WriteStartObject(); -// // writer.WritePropertyName(textFrequency.Text); -// // writer.WriteNumberValue(textFrequency.Percent); -// // writer.WriteEndObject(); -// // } -// // } -// -// -// -// } \ No newline at end of file diff --git a/csharp/Lib/SysTools/Edges/StringToCommand.cs b/csharp/Lib/SysTools/Edges/StringToCommand.cs index 1dc691b7f..62c595f75 100644 --- a/csharp/Lib/SysTools/Edges/StringToCommand.cs +++ b/csharp/Lib/SysTools/Edges/StringToCommand.cs @@ -7,50 +7,50 @@ public static class StringToCommand public static SysCommand Opt1(this String cmd, String option) { return cmd - .ToCommand() - .Opt1(option); + .ToCommand() + .Opt1(option); } public static SysCommand Opt1(this String cmd, String option, Object value, String separator = " ") { return cmd - .ToCommand() - .Opt1(option, value, separator); + .ToCommand() + .Opt1(option, value, separator); } public static SysCommand Opt2(this String cmd, String option) { return cmd - .ToCommand() - .Opt2(option); + .ToCommand() + .Opt2(option); } public static SysCommand Opt2(this String cmd, String option, Object value, String separator = "=") { return cmd - .ToCommand() - .Opt2(option, value, separator); + .ToCommand() + .Opt2(option, value, separator); } public static SysCommand Opt(this String cmd, String option) { return cmd - .ToCommand() - .Opt(option); + .ToCommand() + .Opt(option); } public static SysCommand Opt(this String cmd, String option, Object value) { return cmd - .ToCommand() - .Opt(option, value); + .ToCommand() + .Opt(option, value); } public static SysCommand Arg(this String cmd, Object argument) { return cmd - .ToCommand() - .Arg(argument); + .ToCommand() + .Arg(argument); } } \ No newline at end of file diff --git a/csharp/Lib/SysTools/FileIo.cs b/csharp/Lib/SysTools/FileIo.cs index 7328bd324..bec888e56 100644 --- a/csharp/Lib/SysTools/FileIo.cs +++ b/csharp/Lib/SysTools/FileIo.cs @@ -1,8 +1,9 @@ using System.Text; -using InnovEnergy.Lib.SysTools.Utils; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.SysTools; +[Obsolete("Needs rework before use")] public static class FileIo { public static Boolean Exists (this SysPath path) => path.FileExists() || path.DirectoryExists(); @@ -14,12 +15,12 @@ public static class FileIo public static IEnumerable Directories(this SysPath sysPath) => Directory - .GetDirectories(sysPath) - .Select(SysPath.FromString); + .GetDirectories(sysPath) + .Select(SysPath.FromString); public static IEnumerable Files(this SysPath sysPath) => Directory - .GetFiles(sysPath) - .Select(SysPath.FromString); + .GetFiles(sysPath) + .Select(SysPath.FromString); public static SysPath CreateDirectory(this SysPath path) @@ -91,10 +92,10 @@ public static class FileIo SysPath Target(SysPath path) => targetDir.Append(path.RelativeTo(sourceDir)); - Utils.Utils.Traverse(sourceDir, Directories) - .Do(d => Target(d).CreateDirectory()) - .SelectMany(Files) - .ForEach(f => f.CopyFileTo(Target(f))); + sourceDir.Traverse(Directories) + .Do(d => Target(d).CreateDirectory()) + .SelectMany(Files) + .ForEach(f => f.CopyFileTo(Target(f))); return sourceDir; } @@ -115,14 +116,14 @@ public static class FileIo public static IEnumerable DescendantDirectories(this SysPath path) { - return Utils.Utils.Traverse(path, Directories); + return path.Traverse(Directories); } public static IEnumerable DescendantFiles(this SysPath path) { return path - .DescendantDirectories() - .SelectMany(Files); + .DescendantDirectories() + .SelectMany(Files); } public static IEnumerable Descendants(this SysPath path) @@ -140,13 +141,11 @@ public static class FileIo { var buf = new Byte[4096]; - using (var fs = File.OpenRead(path)) - { - var n = fs.Read(buf, 0, buf.Length); + using var fs = File.OpenRead(path); + var n = fs.Read(buf, 0, buf.Length); - foreach (var b in buf.Take(Math.Max(0, n))) - yield return b; - } + foreach (var b in buf.Take(Math.Max(0, n))) + yield return b; } @@ -154,29 +153,29 @@ public static class FileIo public static IEnumerable ReadLines(this SysPath path, Encoding encoding) { - using (var sr = new StreamReader(path, encoding)) - while (true) - { - var str = sr.ReadLine(); - if (str == null) - yield break; + using var sr = new StreamReader(path, encoding); + while (true) + { + var str = sr.ReadLine(); + if (str == null) + yield break; - yield return str; - } + yield return str; + } } public static String ReadText(this SysPath path) => path.ReadText(Encoding.UTF8); public static String ReadText(this SysPath path, Encoding encoding) { - using (var sr = new StreamReader(path, encoding)) - return sr.ReadToEnd(); + using var sr = new StreamReader(path, encoding); + return sr.ReadToEnd(); } public static SysPath WriteText(this SysPath filePath, String text) { - using (var sw = new StreamWriter(filePath, append: false)) - sw.Write(text); + using var sw = new StreamWriter(filePath, append: false); + sw.Write(text); return filePath; } @@ -189,17 +188,17 @@ public static class FileIo public static SysPath WriteLines(this SysPath filePath, IEnumerable lines) { - using (var sw = new StreamWriter(filePath, append: false)) - foreach (var line in lines) - sw.WriteLine(line); + using var sw = new StreamWriter(filePath, append: false); + foreach (var line in lines) + sw.WriteLine(line); return filePath; } public static SysPath AppendText(this SysPath filePath, String text) { - using (var sw = new StreamWriter(filePath, append: true)) - sw.Write(text); + using var sw = new StreamWriter(filePath, append: true); + sw.Write(text); return filePath; } @@ -212,9 +211,9 @@ public static class FileIo public static SysPath AppendLines(this SysPath filePath, IEnumerable lines) { - using (var sw = new StreamWriter(filePath, append: true)) - foreach (var line in lines) - sw.WriteLine(line); + using var sw = new StreamWriter(filePath, append: true); + foreach (var line in lines) + sw.WriteLine(line); return filePath; } diff --git a/csharp/Lib/SysTools/Process/AsyncProcess.cs b/csharp/Lib/SysTools/Process/AsyncProcess.cs index 3fb9e967f..ee0137482 100644 --- a/csharp/Lib/SysTools/Process/AsyncProcess.cs +++ b/csharp/Lib/SysTools/Process/AsyncProcess.cs @@ -9,6 +9,7 @@ namespace InnovEnergy.Lib.SysTools.Process; using Env = Dictionary; +[Obsolete("Use CliWrap instead")] public class AsyncProcess { private readonly Subject _StandardIn; diff --git a/csharp/Lib/SysTools/Process/ProcessResult.cs b/csharp/Lib/SysTools/Process/ProcessResult.cs index 162a2280d..e8af589b3 100644 --- a/csharp/Lib/SysTools/Process/ProcessResult.cs +++ b/csharp/Lib/SysTools/Process/ProcessResult.cs @@ -2,6 +2,7 @@ using InnovEnergy.Lib.SysTools.Utils; namespace InnovEnergy.Lib.SysTools.Process; +[Obsolete("Use CliWrap instead")] public readonly struct ProcessResult { public ProcessResult(Int32 exitCode, diff --git a/csharp/Lib/SysTools/Process/SyncProcess.cs b/csharp/Lib/SysTools/Process/SyncProcess.cs index 36caedf3a..7d47f447f 100644 --- a/csharp/Lib/SysTools/Process/SyncProcess.cs +++ b/csharp/Lib/SysTools/Process/SyncProcess.cs @@ -7,7 +7,7 @@ namespace InnovEnergy.Lib.SysTools.Process; using Env = Dictionary; - +[Obsolete("Use CliWrap instead")] public class SyncProcess { public SysCommand Command { get; } diff --git a/csharp/Lib/SysTools/Remote/RemoteCommand.cs b/csharp/Lib/SysTools/Remote/RemoteCommand.cs index 69e59d571..fa80d2671 100644 --- a/csharp/Lib/SysTools/Remote/RemoteCommand.cs +++ b/csharp/Lib/SysTools/Remote/RemoteCommand.cs @@ -2,6 +2,7 @@ using InnovEnergy.Lib.SysTools.Utils; namespace InnovEnergy.Lib.SysTools.Remote; +[Obsolete("Use CliWrap instead")] public readonly struct RemoteCommand { public SshHost Host { get; } diff --git a/csharp/Lib/SysTools/Remote/RemoteFileIo.cs b/csharp/Lib/SysTools/Remote/RemoteFileIo.cs index 1444b5539..e317d7227 100644 --- a/csharp/Lib/SysTools/Remote/RemoteFileIo.cs +++ b/csharp/Lib/SysTools/Remote/RemoteFileIo.cs @@ -3,6 +3,7 @@ using InnovEnergy.Lib.SysTools.Utils; namespace InnovEnergy.Lib.SysTools.Remote; +[Obsolete("Needs rework before use")] public static class RemoteFileIo { diff --git a/csharp/Lib/SysTools/Remote/RemotePath.cs b/csharp/Lib/SysTools/Remote/RemotePath.cs index 97b21da39..dcb75adb3 100644 --- a/csharp/Lib/SysTools/Remote/RemotePath.cs +++ b/csharp/Lib/SysTools/Remote/RemotePath.cs @@ -1,5 +1,6 @@ namespace InnovEnergy.Lib.SysTools.Remote; +[Obsolete] public readonly struct RemotePath { public SysPath Path { get; } diff --git a/csharp/Lib/SysTools/Remote/SshHost.cs b/csharp/Lib/SysTools/Remote/SshHost.cs index 5afade016..a957f2887 100644 --- a/csharp/Lib/SysTools/Remote/SshHost.cs +++ b/csharp/Lib/SysTools/Remote/SshHost.cs @@ -3,6 +3,7 @@ using InnovEnergy.Lib.SysTools.Utils; namespace InnovEnergy.Lib.SysTools.Remote; +[Obsolete("Needs rework before use")] public readonly struct SshHost { public const Int32 DefaultPort = 22; diff --git a/csharp/Lib/SysTools/SysCommand.cs b/csharp/Lib/SysTools/SysCommand.cs index 9d264c27d..50237a5d8 100644 --- a/csharp/Lib/SysTools/SysCommand.cs +++ b/csharp/Lib/SysTools/SysCommand.cs @@ -2,6 +2,7 @@ using InnovEnergy.Lib.SysTools.Utils; namespace InnovEnergy.Lib.SysTools; +[Obsolete("Use CliWrap instead")] public readonly struct SysCommand { public SysPath Path { get; } diff --git a/csharp/Lib/SysTools/SysDirs.cs b/csharp/Lib/SysTools/SysDirs.cs index 5c3c5bc68..c65d4e7b7 100644 --- a/csharp/Lib/SysTools/SysDirs.cs +++ b/csharp/Lib/SysTools/SysDirs.cs @@ -3,6 +3,7 @@ using static System.Environment.SpecialFolder; namespace InnovEnergy.Lib.SysTools; +[Obsolete] public static class SysDirs { diff --git a/csharp/Lib/SysTools/SysPath.cs b/csharp/Lib/SysTools/SysPath.cs index 383460ab8..b5ff40c36 100644 --- a/csharp/Lib/SysTools/SysPath.cs +++ b/csharp/Lib/SysTools/SysPath.cs @@ -5,6 +5,7 @@ using static System.IO.Path; namespace InnovEnergy.Lib.SysTools; +[Obsolete("Needs rework before use")] public readonly struct SysPath { private readonly String _Path; diff --git a/csharp/Lib/SysTools/SysTools.csproj b/csharp/Lib/SysTools/SysTools.csproj index 9fd38651b..629608dc6 100644 --- a/csharp/Lib/SysTools/SysTools.csproj +++ b/csharp/Lib/SysTools/SysTools.csproj @@ -5,4 +5,8 @@ + + + + diff --git a/csharp/Lib/SysTools/Utils/EnumerableUtils.cs b/csharp/Lib/SysTools/Utils/EnumerableUtils.cs index 16d6c8671..9f02caacf 100644 --- a/csharp/Lib/SysTools/Utils/EnumerableUtils.cs +++ b/csharp/Lib/SysTools/Utils/EnumerableUtils.cs @@ -5,14 +5,12 @@ internal static class EnumerableUtils public static IEnumerable Pad(this IEnumerable src, Int32 length, T padding) { - using (var enumerator = src.GetEnumerator()) - { - while (enumerator.MoveNext() && length-- > 0) - yield return enumerator.Current; + using var enumerator = src.GetEnumerator(); + while (enumerator.MoveNext() && length-- > 0) + yield return enumerator.Current; - while (length-- > 0) - yield return padding; - } + while (length-- > 0) + yield return padding; } public static Dictionary> IndexColumn(this IEnumerable> src, UInt16 index) @@ -33,10 +31,10 @@ internal static class EnumerableUtils public static IEnumerable<(TLeft left, TRight right)> Zip(IEnumerable left, IEnumerable right) { - using (var l = left.GetEnumerator()) - using (var r = right.GetEnumerator()) - while (l.MoveNext() && r.MoveNext()) - yield return (l.Current, r.Current); + using var l = left.GetEnumerator(); + using var r = right.GetEnumerator(); + while (l.MoveNext() && r.MoveNext()) + yield return (l.Current, r.Current); } public static IEnumerator Enumerator(this T t) @@ -57,20 +55,6 @@ internal static class EnumerableUtils action(e); } - public static IEnumerable Do(this IEnumerable enumerable, Action action) - { - return enumerable.Select(e => - { - action(e); - return e; - }); - } - - public static void ForEach(this IEnumerable enumerable, Func func) - { - foreach (var e in enumerable) - func(e); - } public static IEnumerable WhereNot(this IEnumerable enumerable, Func predicate) diff --git a/csharp/Lib/SysTools/Utils/Utils.cs b/csharp/Lib/SysTools/Utils/Utils.cs index 73e37198e..026c63e8c 100644 --- a/csharp/Lib/SysTools/Utils/Utils.cs +++ b/csharp/Lib/SysTools/Utils/Utils.cs @@ -2,55 +2,6 @@ namespace InnovEnergy.Lib.SysTools.Utils; public static class Utils { - public static IEnumerable Traverse(T root, Func> getChildren) - { - var stack = new Stack>(); - var it = root.Enumerator(); - it.MoveNext(); - - while (true) - { - //////// going down //////// - - while (true) - { - var cit = getChildren(it.Current).GetEnumerator(); - - if (cit.MoveNext()) // node has children, must be a branch - { - yield return it.Current; - - stack.Push(it); - it = cit; - } - else // no children, hence a leaf - { - var node = it.Current; - - yield return node; - - if (!it.MoveNext()) - break; // no more siblings: goto parent - } - } - - //////// going up //////// - - while (true) - { - it.Dispose(); - if (stack.Count == 0) yield break; // we got to the bottom of the stack, were done - - it = stack.Pop(); - - if (it.MoveNext()) - break; - } - } - - - } - private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); @@ -59,7 +10,6 @@ public static class Utils return Epoch.AddSeconds(unixTime); } - public static R ValueOrDefault(this Dictionary dict, T key) { return ValueOrDefault(dict, key, default); diff --git a/csharp/Lib/Utils/Utils.cs b/csharp/Lib/Utils/Utils.cs index b07ab7111..f4e5deb88 100644 --- a/csharp/Lib/Utils/Utils.cs +++ b/csharp/Lib/Utils/Utils.cs @@ -76,8 +76,8 @@ public static class Utils var res = index % length; return res >= 0 - ? res - : res + length; + ? res + : res + length; } public static IEnumerable Traverse(this T root, Func> getChildren) From afa662a843cf26ff4f39ef16f6a84a8259caa79a Mon Sep 17 00:00:00 2001 From: ig Date: Sat, 25 Feb 2023 16:52:26 +0100 Subject: [PATCH 013/114] Add Meta Solution Folder --- csharp/InnovEnergy.sln | 9 +++++++++ csharp/InnovEnergy.sln.DotSettings | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 88f01a87d..b3c6b3b26 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -63,6 +63,15 @@ EndProject EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusData", "Lib\StatusData\StatusData.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Meta", "Meta", "{AED84693-C389-44C9-B2C0-ACB560189CF2}" + ProjectSection(SolutionItems) = preProject + InnovEnergy.props = InnovEnergy.props + App\InnovEnergy.App.props = App\InnovEnergy.App.props + Lib\InnovEnergy.Lib.props = Lib\InnovEnergy.Lib.props + InnovEnergy.sln.DotSettings = InnovEnergy.sln.DotSettings + EndProjectSection +EndProject + Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/csharp/InnovEnergy.sln.DotSettings b/csharp/InnovEnergy.sln.DotSettings index b1ba507d9..308df85e9 100644 --- a/csharp/InnovEnergy.sln.DotSettings +++ b/csharp/InnovEnergy.sln.DotSettings @@ -33,4 +33,5 @@ True True True - True \ No newline at end of file + True + \ No newline at end of file From 13942bfaf5f55d646c93fc645e10b7071e76fe63 Mon Sep 17 00:00:00 2001 From: ig Date: Sat, 25 Feb 2023 18:57:45 +0100 Subject: [PATCH 014/114] remove stray package-lock.json --- package-lock.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 7ff72816a..000000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "new", - "lockfileVersion": 2, - "requires": true, - "packages": {} -} From fd1b47978311bb931fa9fa048261c8e5f0e1d1c5 Mon Sep 17 00:00:00 2001 From: ig Date: Sun, 26 Feb 2023 10:38:28 +0100 Subject: [PATCH 015/114] move Phases from StatusApi.csproj to Units.csproj --- csharp/InnovEnergy.sln | 2 +- csharp/InnovEnergy.sln.DotSettings | 5 +- csharp/Lib/StatusApi/BatteryStatus.cs | 7 ++ .../Lib/StatusApi/Connections/DcConnection.cs | 8 -- .../StatusApi/Connections/IAc1Connection.cs | 8 ++ .../StatusApi/Connections/IAc3Connection.cs | 8 ++ .../StatusApi/Connections/IDcConnection.cs | 9 +++ .../StatusApi/Connections/IPvConnection.cs | 8 ++ .../Connections/SinglePhaseAcConnection.cs | 12 --- .../Connections/ThreePhaseAcConnection.cs | 10 --- csharp/Lib/StatusApi/DcDcConverterStatus.cs | 8 ++ .../{Devices/Device.cs => DeviceStatus.cs} | 6 +- csharp/Lib/StatusApi/DeviceType.cs | 34 --------- csharp/Lib/StatusApi/Devices/Battery.cs | 12 --- csharp/Lib/StatusApi/Devices/DcDcConverter.cs | 10 --- csharp/Lib/StatusApi/Devices/DcDevice.cs | 5 -- csharp/Lib/StatusApi/Devices/GridMeter.cs | 5 -- .../Lib/StatusApi/Devices/IPvCoupledDevice.cs | 8 -- csharp/Lib/StatusApi/Devices/Mppt.cs | 10 --- .../StatusApi/Devices/SinglePhaseAcDevice.cs | 6 -- .../StatusApi/Devices/SinglePhaseInverter.cs | 7 -- .../Devices/SinglePhasePvInverter.cs | 10 --- .../StatusApi/Devices/ThreePhaseAcDevice.cs | 5 -- .../StatusApi/Devices/ThreePhaseInverter.cs | 12 --- .../StatusApi/Devices/ThreePhasePvInverter.cs | 10 --- csharp/Lib/StatusApi/MpptStatus.cs | 8 ++ csharp/Lib/StatusApi/Phases/AcPhase.cs | 35 --------- csharp/Lib/StatusApi/Phases/Phase.cs | 12 --- csharp/Lib/StatusApi/PowerMeterStatus.cs | 6 ++ .../StatusApi/SinglePhaseInverterStatus.cs | 9 +++ .../StatusApi/SinglePhasePvInverterStatus.cs | 9 +++ csharp/Lib/StatusApi/StatusApi.csproj | 1 + .../Lib/StatusApi/ThreePhaseInverterStatus.cs | 10 +++ .../StatusApi/ThreePhasePvInverterStatus.cs | 9 +++ csharp/Lib/StatusData/Current.cs | 32 -------- csharp/Lib/StatusData/Json/Converters.cs | 16 ---- csharp/Lib/StatusData/Power.cs | 33 --------- csharp/Lib/StatusData/Resistance.cs | 35 --------- csharp/Lib/StatusData/Units.cs | 9 --- csharp/Lib/StatusData/Voltage.cs | 32 -------- csharp/Lib/Units/Angle.cs | 73 +++++++++++++++++++ csharp/Lib/Units/Composite/Ac1Phase.cs | 10 +++ csharp/Lib/Units/Composite/Ac3Phase.cs | 8 ++ csharp/Lib/Units/Composite/AcPhase.cs | 22 ++++++ csharp/Lib/Units/Composite/DcPhase.cs | 6 ++ csharp/Lib/Units/Composite/Phase.cs | 7 ++ csharp/Lib/Units/Frequency.cs | 59 +++++++++++++++ .../Json/CurrentConverter.cs | 2 +- .../Json/PowerConverter.cs | 2 +- .../Json/ResistanceConverter.cs | 2 +- .../Json/VoltageConverter.cs | 2 +- csharp/Lib/Units/Power.cs | 66 +++++++++++++++++ csharp/Lib/Units/Resistance.cs | 63 ++++++++++++++++ csharp/Lib/{StatusData => Units}/State.cs | 9 +-- csharp/Lib/Units/Temperature.cs | 61 ++++++++++++++++ csharp/Lib/Units/Units.cs | 20 +++++ .../StatusData.csproj => Units/Units.csproj} | 8 ++ csharp/Lib/Units/Voltage.cs | 69 ++++++++++++++++++ csharp/Lib/Utils/Units.cs | 15 ---- csharp/Lib/Utils/Utils.cs | 9 +++ 60 files changed, 596 insertions(+), 398 deletions(-) create mode 100644 csharp/Lib/StatusApi/BatteryStatus.cs delete mode 100644 csharp/Lib/StatusApi/Connections/DcConnection.cs create mode 100644 csharp/Lib/StatusApi/Connections/IAc1Connection.cs create mode 100644 csharp/Lib/StatusApi/Connections/IAc3Connection.cs create mode 100644 csharp/Lib/StatusApi/Connections/IDcConnection.cs create mode 100644 csharp/Lib/StatusApi/Connections/IPvConnection.cs delete mode 100644 csharp/Lib/StatusApi/Connections/SinglePhaseAcConnection.cs delete mode 100644 csharp/Lib/StatusApi/Connections/ThreePhaseAcConnection.cs create mode 100644 csharp/Lib/StatusApi/DcDcConverterStatus.cs rename csharp/Lib/StatusApi/{Devices/Device.cs => DeviceStatus.cs} (59%) delete mode 100644 csharp/Lib/StatusApi/DeviceType.cs delete mode 100644 csharp/Lib/StatusApi/Devices/Battery.cs delete mode 100644 csharp/Lib/StatusApi/Devices/DcDcConverter.cs delete mode 100644 csharp/Lib/StatusApi/Devices/DcDevice.cs delete mode 100644 csharp/Lib/StatusApi/Devices/GridMeter.cs delete mode 100644 csharp/Lib/StatusApi/Devices/IPvCoupledDevice.cs delete mode 100644 csharp/Lib/StatusApi/Devices/Mppt.cs delete mode 100644 csharp/Lib/StatusApi/Devices/SinglePhaseAcDevice.cs delete mode 100644 csharp/Lib/StatusApi/Devices/SinglePhaseInverter.cs delete mode 100644 csharp/Lib/StatusApi/Devices/SinglePhasePvInverter.cs delete mode 100644 csharp/Lib/StatusApi/Devices/ThreePhaseAcDevice.cs delete mode 100644 csharp/Lib/StatusApi/Devices/ThreePhaseInverter.cs delete mode 100644 csharp/Lib/StatusApi/Devices/ThreePhasePvInverter.cs create mode 100644 csharp/Lib/StatusApi/MpptStatus.cs delete mode 100644 csharp/Lib/StatusApi/Phases/AcPhase.cs delete mode 100644 csharp/Lib/StatusApi/Phases/Phase.cs create mode 100644 csharp/Lib/StatusApi/PowerMeterStatus.cs create mode 100644 csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs create mode 100644 csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs create mode 100644 csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs create mode 100644 csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs delete mode 100644 csharp/Lib/StatusData/Current.cs delete mode 100644 csharp/Lib/StatusData/Json/Converters.cs delete mode 100644 csharp/Lib/StatusData/Power.cs delete mode 100644 csharp/Lib/StatusData/Resistance.cs delete mode 100644 csharp/Lib/StatusData/Units.cs delete mode 100644 csharp/Lib/StatusData/Voltage.cs create mode 100644 csharp/Lib/Units/Angle.cs create mode 100644 csharp/Lib/Units/Composite/Ac1Phase.cs create mode 100644 csharp/Lib/Units/Composite/Ac3Phase.cs create mode 100644 csharp/Lib/Units/Composite/AcPhase.cs create mode 100644 csharp/Lib/Units/Composite/DcPhase.cs create mode 100644 csharp/Lib/Units/Composite/Phase.cs create mode 100644 csharp/Lib/Units/Frequency.cs rename csharp/Lib/{StatusData => Units}/Json/CurrentConverter.cs (91%) rename csharp/Lib/{StatusData => Units}/Json/PowerConverter.cs (90%) rename csharp/Lib/{StatusData => Units}/Json/ResistanceConverter.cs (91%) rename csharp/Lib/{StatusData => Units}/Json/VoltageConverter.cs (91%) create mode 100644 csharp/Lib/Units/Power.cs create mode 100644 csharp/Lib/Units/Resistance.cs rename csharp/Lib/{StatusData => Units}/State.cs (73%) create mode 100644 csharp/Lib/Units/Temperature.cs create mode 100644 csharp/Lib/Units/Units.cs rename csharp/Lib/{StatusData/StatusData.csproj => Units/Units.csproj} (52%) create mode 100644 csharp/Lib/Units/Voltage.cs delete mode 100644 csharp/Lib/Utils/Units.cs diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index b3c6b3b26..3a0fa6fcd 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -61,7 +61,7 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "App/Backend/Backend.csproj", "{A56F58C2-B265-435B-A985-53B4D6F49B1A}" EndProject EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusData", "Lib\StatusData\StatusData.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Units", "Lib\Units\Units.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Meta", "Meta", "{AED84693-C389-44C9-B2C0-ACB560189CF2}" ProjectSection(SolutionItems) = preProject diff --git a/csharp/InnovEnergy.sln.DotSettings b/csharp/InnovEnergy.sln.DotSettings index 308df85e9..f48e450b2 100644 --- a/csharp/InnovEnergy.sln.DotSettings +++ b/csharp/InnovEnergy.sln.DotSettings @@ -1,6 +1,8 @@  - False + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + False + True True True @@ -34,4 +36,5 @@ True True True + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/BatteryStatus.cs b/csharp/Lib/StatusApi/BatteryStatus.cs new file mode 100644 index 000000000..0b033b420 --- /dev/null +++ b/csharp/Lib/StatusApi/BatteryStatus.cs @@ -0,0 +1,7 @@ +using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public abstract record BatteryStatus(DcPhase Dc) : DeviceStatus, IDcConnection; + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/DcConnection.cs b/csharp/Lib/StatusApi/Connections/DcConnection.cs deleted file mode 100644 index cac41968d..000000000 --- a/csharp/Lib/StatusApi/Connections/DcConnection.cs +++ /dev/null @@ -1,8 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Phases; -namespace InnovEnergy.Lib.StatusApi.Connections; - - -public record DcConnection(Decimal Voltage, Decimal Current) : Phase(Voltage, Current) -{ - public Decimal Power => (Current * Voltage).Round3(); -} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IAc1Connection.cs b/csharp/Lib/StatusApi/Connections/IAc1Connection.cs new file mode 100644 index 000000000..df3a472a1 --- /dev/null +++ b/csharp/Lib/StatusApi/Connections/IAc1Connection.cs @@ -0,0 +1,8 @@ +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi.Connections; + +public interface IAc1Connection +{ + Ac1Phase Ac1 { get; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IAc3Connection.cs b/csharp/Lib/StatusApi/Connections/IAc3Connection.cs new file mode 100644 index 000000000..231982cf0 --- /dev/null +++ b/csharp/Lib/StatusApi/Connections/IAc3Connection.cs @@ -0,0 +1,8 @@ +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi.Connections; + +public interface IAc3Connection +{ + Ac1Phase Ac3 { get; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IDcConnection.cs b/csharp/Lib/StatusApi/Connections/IDcConnection.cs new file mode 100644 index 000000000..6074a6750 --- /dev/null +++ b/csharp/Lib/StatusApi/Connections/IDcConnection.cs @@ -0,0 +1,9 @@ +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi.Connections; + + +public interface IDcConnection +{ + DcPhase Dc { get; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IPvConnection.cs b/csharp/Lib/StatusApi/Connections/IPvConnection.cs new file mode 100644 index 000000000..a117f2d17 --- /dev/null +++ b/csharp/Lib/StatusApi/Connections/IPvConnection.cs @@ -0,0 +1,8 @@ +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi.Connections; + +public interface IPvConnection +{ + IReadOnlyList Strings { get; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/SinglePhaseAcConnection.cs b/csharp/Lib/StatusApi/Connections/SinglePhaseAcConnection.cs deleted file mode 100644 index 6b8c57b2d..000000000 --- a/csharp/Lib/StatusApi/Connections/SinglePhaseAcConnection.cs +++ /dev/null @@ -1,12 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Phases; - -namespace InnovEnergy.Lib.StatusApi.Connections; - -public record SinglePhaseAcConnection -( - Decimal Voltage, - Decimal Current, - Decimal Phi, - Decimal Frequency -); - //: AcPhase(Voltage, Current, Phi); \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/ThreePhaseAcConnection.cs b/csharp/Lib/StatusApi/Connections/ThreePhaseAcConnection.cs deleted file mode 100644 index f029b2fc4..000000000 --- a/csharp/Lib/StatusApi/Connections/ThreePhaseAcConnection.cs +++ /dev/null @@ -1,10 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Phases; - -namespace InnovEnergy.Lib.StatusApi.Connections; - -public record ThreePhaseAcConnection(AcPhase L1, AcPhase L2, AcPhase L3, Decimal Frequency) -{ - public Decimal ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; - public Decimal ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; - public Decimal ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; -} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/DcDcConverterStatus.cs b/csharp/Lib/StatusApi/DcDcConverterStatus.cs new file mode 100644 index 000000000..cdda395d9 --- /dev/null +++ b/csharp/Lib/StatusApi/DcDcConverterStatus.cs @@ -0,0 +1,8 @@ +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public abstract record DcDcConverterStatus(DcPhase Left, DcPhase Right) : DeviceStatus; + + + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/Device.cs b/csharp/Lib/StatusApi/DeviceStatus.cs similarity index 59% rename from csharp/Lib/StatusApi/Devices/Device.cs rename to csharp/Lib/StatusApi/DeviceStatus.cs index 879e03326..f34a37d23 100644 --- a/csharp/Lib/StatusApi/Devices/Device.cs +++ b/csharp/Lib/StatusApi/DeviceStatus.cs @@ -1,6 +1,6 @@ -namespace InnovEnergy.Lib.StatusApi.Devices; +namespace InnovEnergy.Lib.StatusApi; -public abstract record Device +public abstract record DeviceStatus { public String DeviceType { @@ -11,7 +11,7 @@ public abstract record Device while (!t!.IsAbstract) t = t.BaseType; - return t.Name; + return t.Name.Replace("Status", ""); } } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/DeviceType.cs b/csharp/Lib/StatusApi/DeviceType.cs deleted file mode 100644 index 47b391875..000000000 --- a/csharp/Lib/StatusApi/DeviceType.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace InnovEnergy.Lib.StatusApi; - -/// SIGN CONVENTION -/// -/// Voltages have to be measured/indicated so that they are guaranteed to be never negative. -/// In the case of AC this is accomplished by using the RMS measurement. -/// The sign convention of the current (and hence power, since voltage defined to be never negative) -/// depends on the type of the device. -/// If the device can only produce (e.g. PV) or only consume (e.g. Loads), -/// then the current has to be 0 or positive. -/// If the device is a prosumer (e.g. inverter, battery, grid...) -/// then a positive sign denotes current (power) flow away from the grid (to the "right") -/// and a negative sign denotes current (power) flow towards the grid (to the "left") - - - - -/// the currently known DeviceTypes, to be serialized as string in JSON -public enum DeviceType -{ - None, - PvOnAcIn , - PvOnAcOut , - PvOnDc , - Load , - CriticalLoad, - Battery , - Grid , - Inverter , - AcInToAcOut , - DcDc , - DcLoad , - Losses -} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/Battery.cs b/csharp/Lib/StatusApi/Devices/Battery.cs deleted file mode 100644 index 3b8b1d476..000000000 --- a/csharp/Lib/StatusApi/Devices/Battery.cs +++ /dev/null @@ -1,12 +0,0 @@ - -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record Battery - ( - DcConnection Dc, - Decimal Soc, - Decimal Temperature - ) - : DcDevice(Dc); \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/DcDcConverter.cs b/csharp/Lib/StatusApi/Devices/DcDcConverter.cs deleted file mode 100644 index dd754d1f1..000000000 --- a/csharp/Lib/StatusApi/Devices/DcDcConverter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record DcDcConverter -( - DcConnection Left, - DcConnection Right -) - : Device; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/DcDevice.cs b/csharp/Lib/StatusApi/Devices/DcDevice.cs deleted file mode 100644 index 280086f26..000000000 --- a/csharp/Lib/StatusApi/Devices/DcDevice.cs +++ /dev/null @@ -1,5 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record DcDevice(DcConnection Dc) : Device; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/GridMeter.cs b/csharp/Lib/StatusApi/Devices/GridMeter.cs deleted file mode 100644 index 32223244b..000000000 --- a/csharp/Lib/StatusApi/Devices/GridMeter.cs +++ /dev/null @@ -1,5 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record GridMeter(ThreePhaseAcConnection Ac) : ThreePhaseAcDevice(Ac); \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/IPvCoupledDevice.cs b/csharp/Lib/StatusApi/Devices/IPvCoupledDevice.cs deleted file mode 100644 index 53281d8ce..000000000 --- a/csharp/Lib/StatusApi/Devices/IPvCoupledDevice.cs +++ /dev/null @@ -1,8 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public interface IPvCoupledDevice -{ - IReadOnlyList Strings { get; } -} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/Mppt.cs b/csharp/Lib/StatusApi/Devices/Mppt.cs deleted file mode 100644 index 2e9630d22..000000000 --- a/csharp/Lib/StatusApi/Devices/Mppt.cs +++ /dev/null @@ -1,10 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record Mppt - ( - DcConnection Dc, - IReadOnlyList Strings - ) - : DcDevice(Dc), IPvCoupledDevice; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/SinglePhaseAcDevice.cs b/csharp/Lib/StatusApi/Devices/SinglePhaseAcDevice.cs deleted file mode 100644 index 4e259e05a..000000000 --- a/csharp/Lib/StatusApi/Devices/SinglePhaseAcDevice.cs +++ /dev/null @@ -1,6 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - - -public abstract record SinglePhaseAcDevice(SinglePhaseAcConnection Ac) : Device; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/SinglePhaseInverter.cs b/csharp/Lib/StatusApi/Devices/SinglePhaseInverter.cs deleted file mode 100644 index d63747161..000000000 --- a/csharp/Lib/StatusApi/Devices/SinglePhaseInverter.cs +++ /dev/null @@ -1,7 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record SinglePhaseInverter(SinglePhaseAcConnection Ac, DcConnection Dc); - - diff --git a/csharp/Lib/StatusApi/Devices/SinglePhasePvInverter.cs b/csharp/Lib/StatusApi/Devices/SinglePhasePvInverter.cs deleted file mode 100644 index bf0a65c50..000000000 --- a/csharp/Lib/StatusApi/Devices/SinglePhasePvInverter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record SinglePhasePvInverter - ( - SinglePhaseAcConnection Ac, - IReadOnlyList Strings - ) - : SinglePhaseAcDevice(Ac), IPvCoupledDevice; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/ThreePhaseAcDevice.cs b/csharp/Lib/StatusApi/Devices/ThreePhaseAcDevice.cs deleted file mode 100644 index 340218e09..000000000 --- a/csharp/Lib/StatusApi/Devices/ThreePhaseAcDevice.cs +++ /dev/null @@ -1,5 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record ThreePhaseAcDevice(ThreePhaseAcConnection Ac) : Device; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/ThreePhaseInverter.cs b/csharp/Lib/StatusApi/Devices/ThreePhaseInverter.cs deleted file mode 100644 index 895a9edf2..000000000 --- a/csharp/Lib/StatusApi/Devices/ThreePhaseInverter.cs +++ /dev/null @@ -1,12 +0,0 @@ - - -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record ThreePhaseInverter - ( - ThreePhaseAcConnection Ac, - DcConnection Dc - ) - : Device; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Devices/ThreePhasePvInverter.cs b/csharp/Lib/StatusApi/Devices/ThreePhasePvInverter.cs deleted file mode 100644 index ad07f5202..000000000 --- a/csharp/Lib/StatusApi/Devices/ThreePhasePvInverter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using InnovEnergy.Lib.StatusApi.Connections; - -namespace InnovEnergy.Lib.StatusApi.Devices; - -public abstract record ThreePhasePvInverter - ( - ThreePhaseAcConnection Ac, - IReadOnlyList Strings - ) - : ThreePhaseAcDevice(Ac), IPvCoupledDevice; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/MpptStatus.cs b/csharp/Lib/StatusApi/MpptStatus.cs new file mode 100644 index 000000000..bec31ddec --- /dev/null +++ b/csharp/Lib/StatusApi/MpptStatus.cs @@ -0,0 +1,8 @@ +using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public record MpptStatus(DcPhase Dc, IReadOnlyList Strings) : IDcConnection, IPvConnection; + + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Phases/AcPhase.cs b/csharp/Lib/StatusApi/Phases/AcPhase.cs deleted file mode 100644 index 068e19393..000000000 --- a/csharp/Lib/StatusApi/Phases/AcPhase.cs +++ /dev/null @@ -1,35 +0,0 @@ -using static DecimalMath.DecimalEx; - -namespace InnovEnergy.Lib.StatusApi.Phases; - - -public record AcPhase(Decimal Voltage, Decimal Current, Decimal Phi) - : Phase(Voltage, Current) -{ - - public Decimal ApparentPower => Voltage * Current; - public Decimal ActivePower => ApparentPower * PowerFactor; - public Decimal ReactivePower => ApparentPower * Sin(Phi); - public Decimal PowerFactor => Cos(Phi); - - public static AcPhase FromActiveReactive - ( - Decimal activePower, - Decimal reactivePower, - Decimal voltage, - Decimal current - ) - { - var phi = ATan2(reactivePower, activePower); - - return new AcPhase - ( - Voltage: voltage, - Current: current, - Phi: phi - ); - - } - - -} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Phases/Phase.cs b/csharp/Lib/StatusApi/Phases/Phase.cs deleted file mode 100644 index 236d6cf77..000000000 --- a/csharp/Lib/StatusApi/Phases/Phase.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace InnovEnergy.Lib.StatusApi.Phases; - -/// A phase must have at least a known Voltage and Current. -/// For DC this is already enough. -/// For AC the values have to be in RMS (not amplitude or P2P) -/// Power can be inferred, P = UI - -public abstract record Phase - ( - Decimal Voltage, - Decimal Current - ); \ No newline at end of file diff --git a/csharp/Lib/StatusApi/PowerMeterStatus.cs b/csharp/Lib/StatusApi/PowerMeterStatus.cs new file mode 100644 index 000000000..41038f4dc --- /dev/null +++ b/csharp/Lib/StatusApi/PowerMeterStatus.cs @@ -0,0 +1,6 @@ +using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public abstract record PowerMeterStatus(Ac1Phase Ac3) : DeviceStatus, IAc3Connection; \ No newline at end of file diff --git a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs new file mode 100644 index 000000000..a1b404bd6 --- /dev/null +++ b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs @@ -0,0 +1,9 @@ +using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public abstract record SinglePhaseInverterStatus(Ac1Phase Ac1, DcPhase Dc) : + DeviceStatus, + IAc1Connection, + IDcConnection; diff --git a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs new file mode 100644 index 000000000..377f9f6f3 --- /dev/null +++ b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs @@ -0,0 +1,9 @@ +using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public abstract record SinglePhasePvInverterStatus(Ac1Phase Ac1, IReadOnlyList Strings) : + DeviceStatus, + IAc1Connection, + IPvConnection; diff --git a/csharp/Lib/StatusApi/StatusApi.csproj b/csharp/Lib/StatusApi/StatusApi.csproj index f1e4bc0f8..88fda982e 100644 --- a/csharp/Lib/StatusApi/StatusApi.csproj +++ b/csharp/Lib/StatusApi/StatusApi.csproj @@ -3,6 +3,7 @@ + diff --git a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs new file mode 100644 index 000000000..8c2fc424f --- /dev/null +++ b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs @@ -0,0 +1,10 @@ +using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public abstract record ThreePhaseInverterStatus(Ac1Phase Ac3, DcPhase Dc) : + DeviceStatus, + IAc3Connection, + IDcConnection; + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs new file mode 100644 index 000000000..c09471d4b --- /dev/null +++ b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs @@ -0,0 +1,9 @@ +using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.Units.Composite; + +namespace InnovEnergy.Lib.StatusApi; + +public abstract record ThreePhasePvInverterStatus(Ac1Phase Ac3, IReadOnlyList Strings) : + DeviceStatus, + IAc3Connection, + IPvConnection; diff --git a/csharp/Lib/StatusData/Current.cs b/csharp/Lib/StatusData/Current.cs deleted file mode 100644 index 2f65add3c..000000000 --- a/csharp/Lib/StatusData/Current.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace InnovEnergy.Lib.StatusData; - -public readonly struct Current -{ - public static String Unit => "A"; - public static String Symbol => "I"; - - public Decimal Value { get; } - - public Current(Decimal value) => Value = value; - - public override String ToString() => Value + Unit; - - - // parallel - public static Current operator |(Current left, Current right) => new Current(left.Value + right.Value); - - // scalar multiplication - public static Current operator *(Decimal scalar , Current current) => new Current(scalar * current.Value); - public static Current operator *(Current current, Decimal scalar) => new Current(scalar * current.Value); - public static Current operator *(Int32 scalar , Current current) => new Current(scalar * current.Value); - public static Current operator *(Current current, Int32 scalar) => new Current(scalar * current.Value); - public static Current operator /(Current current, Decimal scalar) => new Current(current.Value / scalar); - public static Current operator /(Current current, Int32 scalar) => new Current(current.Value / scalar); - - // P=UI - public static Power operator *(Current current, Voltage voltage) => new Power(current.Value * voltage.Value); - - // U=RI - public static Voltage operator *(Current current, Resistance resistance) => new Voltage(resistance.Value* current.Value); - -} \ No newline at end of file diff --git a/csharp/Lib/StatusData/Json/Converters.cs b/csharp/Lib/StatusData/Json/Converters.cs deleted file mode 100644 index ab6a4336b..000000000 --- a/csharp/Lib/StatusData/Json/Converters.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Text.Json.Serialization; -using InnovEnergy.Lib.StatusData.Json; - -// ReSharper disable once CheckNamespace -namespace InnovEnergy.Units; - -public static partial class Units -{ - public static IReadOnlyList JsonConverters = new JsonConverter[] - { - new CurrentConverter(), - new VoltageConverter(), - new PowerConverter(), - new ResistanceConverter() - }; -} \ No newline at end of file diff --git a/csharp/Lib/StatusData/Power.cs b/csharp/Lib/StatusData/Power.cs deleted file mode 100644 index 3a605dfca..000000000 --- a/csharp/Lib/StatusData/Power.cs +++ /dev/null @@ -1,33 +0,0 @@ -using InnovEnergy.Units; - -namespace InnovEnergy.Lib.StatusData; - -public readonly struct Power -{ - public static String Unit => "W"; - public static String Symbol => "P"; - - public Decimal Value { get; } - - public Power(Decimal value) => Value = value; - - public override String ToString() => Value + Unit; - - - // parallel - public static Power operator |(Power left, Power right) => new Power(left.Value + right.Value); - // series - public static Power operator +(Power left, Power right) => new Power(left.Value + right.Value); - - // scalar multiplication - public static Power operator *(Decimal scalar, Power power ) => new Power(scalar * power.Value); - public static Power operator *(Power power , Decimal scalar) => new Power(scalar * power.Value); - public static Power operator *(Int32 scalar, Power power ) => new Power(scalar * power.Value); - public static Power operator *(Power power , Int32 scalar) => new Power(scalar * power.Value); - public static Power operator /(Power power , Decimal scalar) => new Power(power.Value / scalar); - public static Power operator /(Power power , Int32 scalar) => new Power(power.Value / scalar); - - // P=UI - public static Voltage operator /(Power power, Current current) => new Voltage(power.Value / current.Value); - public static Current operator /(Power power, Voltage voltage) => new Current(power.Value / voltage.Value); -} \ No newline at end of file diff --git a/csharp/Lib/StatusData/Resistance.cs b/csharp/Lib/StatusData/Resistance.cs deleted file mode 100644 index d10573e77..000000000 --- a/csharp/Lib/StatusData/Resistance.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace InnovEnergy.Lib.StatusData; - -public readonly struct Resistance -{ - public static String Unit => "Ω"; - public static String Symbol => "R"; - - public Decimal Value { get; } - - public Resistance(Decimal value) => Value = value; - - public override String ToString() => Value + Unit; - - // series - public static Resistance operator +(Resistance left, Resistance right) => new Resistance(left.Value + right.Value); - // parallel - public static Resistance operator |(Resistance left, Resistance right) => new Resistance(1m / (1m / left.Value + 1m / right.Value)); - - // scalar multiplication - public static Resistance operator *(Decimal scalar , Resistance resistance) => new Resistance(scalar * resistance.Value); - public static Resistance operator *(Resistance resistance, Decimal scalar ) => new Resistance(scalar * resistance.Value); - public static Resistance operator *(Int32 scalar , Resistance resistance) => new Resistance(scalar * resistance.Value); - public static Resistance operator *(Resistance resistance, Int32 scalar ) => new Resistance(scalar * resistance.Value); - public static Resistance operator /(Resistance resistance, Decimal scalar ) => new Resistance(resistance.Value / scalar); - public static Resistance operator /(Resistance resistance, Int32 scalar ) => new Resistance(resistance.Value / scalar); - - - // U=RI - public static Voltage operator *(Resistance resistance, Current current) => new Voltage(resistance.Value* current.Value); - - - - // public static Voltage operator /(Power power, Current current) => new Voltage(power.Value / current.Value); - // public static Current operator /(Power power, Voltage voltage) => new Current(power.Value / voltage.Value); -} \ No newline at end of file diff --git a/csharp/Lib/StatusData/Units.cs b/csharp/Lib/StatusData/Units.cs deleted file mode 100644 index 4dacaa297..000000000 --- a/csharp/Lib/StatusData/Units.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace InnovEnergy.Lib.StatusData; - -public static partial class Units -{ - public static Current A (this Decimal value) => new Current(value); - public static Voltage V (this Decimal value) => new Voltage(value); - public static Power W (this Decimal value) => new Power(value); - public static Resistance Ohm(this Decimal value) => new Resistance(value); -} \ No newline at end of file diff --git a/csharp/Lib/StatusData/Voltage.cs b/csharp/Lib/StatusData/Voltage.cs deleted file mode 100644 index fa7c8a7fc..000000000 --- a/csharp/Lib/StatusData/Voltage.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace InnovEnergy.Lib.StatusData; - -public readonly struct Voltage -{ - public static String Unit => "V"; - public static String Symbol => "U"; - - public Decimal Value { get; } - - public Voltage(Decimal value) => Value = value; - - public override String ToString() => Value + Unit; - - - // series - public static Voltage operator +(Voltage left, Voltage right) => new Voltage(left.Value + right.Value); - - public static Voltage operator *(Decimal scalar , Voltage voltage) => new Voltage(scalar * voltage.Value); - public static Voltage operator *(Voltage voltage, Decimal scalar) => new Voltage(scalar * voltage.Value); - public static Voltage operator *(Int32 scalar , Voltage voltage) => new Voltage(scalar * voltage.Value); - public static Voltage operator *(Voltage voltage, Int32 scalar) => new Voltage(scalar * voltage.Value); - - public static Voltage operator /(Voltage voltage, Decimal scalar) => new Voltage(voltage.Value / scalar); - public static Voltage operator /(Voltage voltage, Int32 scalar) => new Voltage(voltage.Value / scalar); - - - // U=RI - public static Current operator /(Voltage voltage, Resistance resistance) => new Current(voltage.Value / resistance.Value); - - // P=UI - public static Power operator *(Voltage voltage, Current current) => new Power(current.Value * voltage.Value); -} \ No newline at end of file diff --git a/csharp/Lib/Units/Angle.cs b/csharp/Lib/Units/Angle.cs new file mode 100644 index 000000000..0f0aa7d8f --- /dev/null +++ b/csharp/Lib/Units/Angle.cs @@ -0,0 +1,73 @@ +using DecimalMath; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.Units; + +using T = Angle; + +public readonly struct Angle +{ + + + public static String Unit => "rad"; + public static String Symbol => "∠"; + + public static readonly Angle Pi = new Angle(DecimalEx.Pi); + + public Decimal Value { get; } + + public Angle(Decimal value) + { + var modulo = value.Modulo(DecimalEx.TwoPi); + + Value = modulo > DecimalEx.Pi + ? modulo - DecimalEx.TwoPi + : modulo; + } + + public override String ToString() => Value + Unit; + + + #region scalar multiplication + + public static Angle operator *(Decimal scalar, Angle angle ) => new Angle(scalar * angle.Value); + public static Angle operator *(Angle angle , Decimal scalar) => new Angle(scalar * angle.Value); + public static Angle operator /(Angle angle , Decimal scalar) => new Angle(angle.Value / scalar); + + #endregion + + #region addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + #endregion + + #region compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + #endregion + + #region conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + #endregion + + #region equality + + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + + #endregion +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/Ac1Phase.cs b/csharp/Lib/Units/Composite/Ac1Phase.cs new file mode 100644 index 000000000..e9970378b --- /dev/null +++ b/csharp/Lib/Units/Composite/Ac1Phase.cs @@ -0,0 +1,10 @@ +namespace InnovEnergy.Lib.Units.Composite; + +public record Ac1Phase + ( + Voltage Voltage, + Current Current, + Angle Phi, + Frequency Frequency + ) : + AcPhase(Voltage, Current, Phi); \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/Ac3Phase.cs b/csharp/Lib/Units/Composite/Ac3Phase.cs new file mode 100644 index 000000000..1fc44306f --- /dev/null +++ b/csharp/Lib/Units/Composite/Ac3Phase.cs @@ -0,0 +1,8 @@ +namespace InnovEnergy.Lib.Units.Composite; + +public record Ac3Phase(AcPhase L1, AcPhase L2, AcPhase L3, Decimal Frequency) +{ + public Power ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; + public Power ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; + public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/AcPhase.cs b/csharp/Lib/Units/Composite/AcPhase.cs new file mode 100644 index 000000000..c616b9c57 --- /dev/null +++ b/csharp/Lib/Units/Composite/AcPhase.cs @@ -0,0 +1,22 @@ +using static DecimalMath.DecimalEx; + +namespace InnovEnergy.Lib.Units.Composite; + + +public record AcPhase : Phase +{ + protected AcPhase(Voltage voltage, Current current, Angle phi) : base(voltage, current) + { + if (voltage < 0) throw new ArgumentException("RMS value cannot be negative", nameof(voltage)); + if (current < 0) throw new ArgumentException("RMS value cannot be negative", nameof(current)); + + Phi = phi; + } + + public Angle Phi { get; } + + public Power ApparentPower => Voltage * Current; + public Power ActivePower => ApparentPower * PowerFactor; + public Power ReactivePower => ApparentPower * Sin(Phi); + public Decimal PowerFactor => Cos(Phi); +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/DcPhase.cs b/csharp/Lib/Units/Composite/DcPhase.cs new file mode 100644 index 000000000..8e73313bf --- /dev/null +++ b/csharp/Lib/Units/Composite/DcPhase.cs @@ -0,0 +1,6 @@ +namespace InnovEnergy.Lib.Units.Composite; + +public record DcPhase(Voltage Voltage, Current Current) : Phase(Voltage, Current) +{ + public Power Power => Current * Voltage; +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/Phase.cs b/csharp/Lib/Units/Composite/Phase.cs new file mode 100644 index 000000000..45a3ef86d --- /dev/null +++ b/csharp/Lib/Units/Composite/Phase.cs @@ -0,0 +1,7 @@ +namespace InnovEnergy.Lib.Units.Composite; + +public abstract record Phase +( + Voltage Voltage, + Current Current +); \ No newline at end of file diff --git a/csharp/Lib/Units/Frequency.cs b/csharp/Lib/Units/Frequency.cs new file mode 100644 index 000000000..91a3e3849 --- /dev/null +++ b/csharp/Lib/Units/Frequency.cs @@ -0,0 +1,59 @@ +namespace InnovEnergy.Lib.Units; + +using T = Frequency; + +public readonly struct Frequency +{ + public static String Unit => "Hz"; + public static String Symbol => "f"; + + public Decimal Value { get; } + + public Frequency(Decimal value) => Value = value; + + public override String ToString() => Value + Unit; + + #region scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + #endregion + + #region addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + #endregion + + #region compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + #endregion + + #region conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + #endregion + + #region equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + + #endregion +} \ No newline at end of file diff --git a/csharp/Lib/StatusData/Json/CurrentConverter.cs b/csharp/Lib/Units/Json/CurrentConverter.cs similarity index 91% rename from csharp/Lib/StatusData/Json/CurrentConverter.cs rename to csharp/Lib/Units/Json/CurrentConverter.cs index 64707325f..b89ec4a90 100644 --- a/csharp/Lib/StatusData/Json/CurrentConverter.cs +++ b/csharp/Lib/Units/Json/CurrentConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Lib.StatusData.Json; +namespace InnovEnergy.Lib.Units.Json; public class CurrentConverter : JsonConverter { diff --git a/csharp/Lib/StatusData/Json/PowerConverter.cs b/csharp/Lib/Units/Json/PowerConverter.cs similarity index 90% rename from csharp/Lib/StatusData/Json/PowerConverter.cs rename to csharp/Lib/Units/Json/PowerConverter.cs index 8c33d3eae..766f3636c 100644 --- a/csharp/Lib/StatusData/Json/PowerConverter.cs +++ b/csharp/Lib/Units/Json/PowerConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Lib.StatusData.Json; +namespace InnovEnergy.Lib.Units.Json; public class PowerConverter : JsonConverter { diff --git a/csharp/Lib/StatusData/Json/ResistanceConverter.cs b/csharp/Lib/Units/Json/ResistanceConverter.cs similarity index 91% rename from csharp/Lib/StatusData/Json/ResistanceConverter.cs rename to csharp/Lib/Units/Json/ResistanceConverter.cs index a60d99009..67ec28a13 100644 --- a/csharp/Lib/StatusData/Json/ResistanceConverter.cs +++ b/csharp/Lib/Units/Json/ResistanceConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Lib.StatusData.Json; +namespace InnovEnergy.Lib.Units.Json; public class ResistanceConverter : JsonConverter { diff --git a/csharp/Lib/StatusData/Json/VoltageConverter.cs b/csharp/Lib/Units/Json/VoltageConverter.cs similarity index 91% rename from csharp/Lib/StatusData/Json/VoltageConverter.cs rename to csharp/Lib/Units/Json/VoltageConverter.cs index b51ceabf5..290c6f38b 100644 --- a/csharp/Lib/StatusData/Json/VoltageConverter.cs +++ b/csharp/Lib/Units/Json/VoltageConverter.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace InnovEnergy.Lib.StatusData.Json; +namespace InnovEnergy.Lib.Units.Json; public class VoltageConverter : JsonConverter { diff --git a/csharp/Lib/Units/Power.cs b/csharp/Lib/Units/Power.cs new file mode 100644 index 000000000..4bc44a53a --- /dev/null +++ b/csharp/Lib/Units/Power.cs @@ -0,0 +1,66 @@ + +namespace InnovEnergy.Lib.Units; + +using T = Power; + +public readonly struct Power +{ + public static String Unit => "W"; + public static String Symbol => "P"; + + public Decimal Value { get; } + + public Power(Decimal value) => Value = value; + + public override String ToString() => Value + Unit; + + + // P=UI + public static Voltage operator /(Power power, Current current) => new Voltage(power.Value / current.Value); + public static Current operator /(Power power, Voltage voltage) => new Current(power.Value / voltage.Value); + + #region scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + #endregion + + #region addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + #endregion + + #region compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + #endregion + + #region conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + #endregion + + #region equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + + #endregion + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Resistance.cs b/csharp/Lib/Units/Resistance.cs new file mode 100644 index 000000000..c3c0b34c0 --- /dev/null +++ b/csharp/Lib/Units/Resistance.cs @@ -0,0 +1,63 @@ +namespace InnovEnergy.Lib.Units; + +using T = Resistance; + +public readonly struct Resistance +{ + public static String Unit => "Ω"; + public static String Symbol => "R"; + + public Decimal Value { get; } + + public Resistance(Decimal value) => Value = value; + + public override String ToString() => Value + Unit; + + // U=RI + public static Voltage operator *(Resistance resistance, Current current) => new Voltage(resistance.Value * current.Value); + + #region scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + #endregion + + #region addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + #endregion + + #region compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + #endregion + + #region conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + #endregion + + #region equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + + #endregion + +} \ No newline at end of file diff --git a/csharp/Lib/StatusData/State.cs b/csharp/Lib/Units/State.cs similarity index 73% rename from csharp/Lib/StatusData/State.cs rename to csharp/Lib/Units/State.cs index 1f91b1249..752a5751d 100644 --- a/csharp/Lib/StatusData/State.cs +++ b/csharp/Lib/Units/State.cs @@ -1,4 +1,4 @@ -namespace InnovEnergy.Lib.StatusData; +namespace InnovEnergy.Lib.Units; public readonly struct State { @@ -9,13 +9,10 @@ public readonly struct State public State(params String[] values) : this((IReadOnlyList)values){} public State(params State[] states) : this(states.SelectMany(s => s.Values).ToList()){} - public State(Enum e) : this(e.ToString()) - { - } + public State(Enum e) : this(e.ToString()){} public static implicit operator State(Enum e) => new State(e); public static implicit operator State(String s) => new State(s); - // parallel - public static State operator |(State left, State right) => new State(left, right); + public static State operator +(State left, State right) => new State(left, right); } \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.cs b/csharp/Lib/Units/Temperature.cs new file mode 100644 index 000000000..22a411338 --- /dev/null +++ b/csharp/Lib/Units/Temperature.cs @@ -0,0 +1,61 @@ +namespace InnovEnergy.Lib.Units; + +using T = Temperature; + +public readonly struct Temperature +{ + public static String Unit => "°C"; + public static String Symbol => "T"; + + public Decimal Value { get; } + + public Temperature(Decimal value) => Value = value; + + public override String ToString() => Value + Unit; + + + #region scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + #endregion + + #region addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + #endregion + + #region compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + #endregion + + #region conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + #endregion + + #region equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + + #endregion + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Units.cs b/csharp/Lib/Units/Units.cs new file mode 100644 index 000000000..88b9e04aa --- /dev/null +++ b/csharp/Lib/Units/Units.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; +using InnovEnergy.Lib.Units.Json; + +namespace InnovEnergy.Lib.Units; + +public static class Units +{ + public static Current A (this Decimal value) => new Current(value); + public static Voltage V (this Decimal value) => new Voltage(value); + public static Power W (this Decimal value) => new Power(value); + public static Resistance Ohm(this Decimal value) => new Resistance(value); + + public static readonly IReadOnlyList JsonConverters = new JsonConverter[] + { + new CurrentConverter(), + new VoltageConverter(), + new PowerConverter(), + new ResistanceConverter() + }; +} \ No newline at end of file diff --git a/csharp/Lib/StatusData/StatusData.csproj b/csharp/Lib/Units/Units.csproj similarity index 52% rename from csharp/Lib/StatusData/StatusData.csproj rename to csharp/Lib/Units/Units.csproj index 69d164c4f..eab4f3f58 100644 --- a/csharp/Lib/StatusData/StatusData.csproj +++ b/csharp/Lib/Units/Units.csproj @@ -6,4 +6,12 @@ preview + + + + + + + + diff --git a/csharp/Lib/Units/Voltage.cs b/csharp/Lib/Units/Voltage.cs new file mode 100644 index 000000000..db75e63e0 --- /dev/null +++ b/csharp/Lib/Units/Voltage.cs @@ -0,0 +1,69 @@ +namespace InnovEnergy.Lib.Units; + +using T = Voltage; + +public readonly struct Voltage +{ + public static String Unit => "V"; + public static String Symbol => "U"; + + public Decimal Value { get; } + + public Voltage(Decimal value) => Value = value; + + public override String ToString() => Value + Unit; + + // U=RI + public static Current operator /(Voltage voltage, Resistance resistance) => new Current(voltage.Value / resistance.Value); + + // P=UI + public static Power operator *(Voltage voltage, Current current) => new Power(current.Value * voltage.Value); + + + #region scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + #endregion + + #region addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + #endregion + + #region compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + #endregion + + #region conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + #endregion + + #region equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + + #endregion + + + +} \ No newline at end of file diff --git a/csharp/Lib/Utils/Units.cs b/csharp/Lib/Utils/Units.cs deleted file mode 100644 index db95bfcbb..000000000 --- a/csharp/Lib/Utils/Units.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace InnovEnergy.Lib.Utils; - -public static class Units -{ - public static String Unit(this Object v, String unit) => $"{v} {unit}"; - - public static String V(this Object v) => v.Unit("V"); - public static String W(this Object v) => v.Unit("W"); - public static String A(this Object v) => v.Unit("A"); - - public static String Degrees(this Object v) => v.Unit("°"); - public static String Celsius(this Object v) => v.Unit("°C"); - public static String Percent(this Object v) => v.Unit("%"); - -} \ No newline at end of file diff --git a/csharp/Lib/Utils/Utils.cs b/csharp/Lib/Utils/Utils.cs index f4e5deb88..690d6abaa 100644 --- a/csharp/Lib/Utils/Utils.cs +++ b/csharp/Lib/Utils/Utils.cs @@ -79,6 +79,15 @@ public static class Utils ? res : res + length; } + + public static Decimal Modulo(this Decimal dividend, Decimal divisor) + { + var res = dividend % divisor; + + return res >= 0 + ? res + : res + divisor; + } public static IEnumerable Traverse(this T root, Func> getChildren) { From 53737a8e1c4d1d6def681068a2cb86bef3692f04 Mon Sep 17 00:00:00 2001 From: ig Date: Sun, 26 Feb 2023 15:39:55 +0100 Subject: [PATCH 016/114] Completely rewrite Units.csproj --- csharp/Lib/Units/Angle.cs | 56 ++---------------- csharp/Lib/Units/ApparentPower.cs | 16 +++++ csharp/Lib/Units/Composite/Ac1Phase.cs | 14 ++--- csharp/Lib/Units/Composite/Ac3Phase.cs | 10 +++- csharp/Lib/Units/Composite/AcPhase.cs | 10 ++-- csharp/Lib/Units/Frequency.cs | 54 ++--------------- .../Lib/Units/Generator/GenerateAttribute.cs | 5 ++ csharp/Lib/Units/Generator/Template.txt | 46 +++++++++++++++ csharp/Lib/Units/Generator/generate.sh | 13 +++++ csharp/Lib/Units/Power.cs | 55 ++---------------- csharp/Lib/Units/Power.generated.cs | 46 +++++++++++++++ csharp/Lib/Units/ReactivePower.cs | 13 +++++ csharp/Lib/Units/Resistance.cs | 54 ++--------------- csharp/Lib/Units/Temperature.cs | 57 ++---------------- csharp/Lib/Units/Units.cs | 17 ++++-- csharp/Lib/Units/Units.csproj | 9 ++- csharp/Lib/Units/Voltage.cs | 58 ++----------------- 17 files changed, 199 insertions(+), 334 deletions(-) create mode 100644 csharp/Lib/Units/ApparentPower.cs create mode 100644 csharp/Lib/Units/Generator/GenerateAttribute.cs create mode 100644 csharp/Lib/Units/Generator/Template.txt create mode 100755 csharp/Lib/Units/Generator/generate.sh create mode 100644 csharp/Lib/Units/Power.generated.cs create mode 100644 csharp/Lib/Units/ReactivePower.cs diff --git a/csharp/Lib/Units/Angle.cs b/csharp/Lib/Units/Angle.cs index 0f0aa7d8f..87a3ed2b4 100644 --- a/csharp/Lib/Units/Angle.cs +++ b/csharp/Lib/Units/Angle.cs @@ -1,20 +1,17 @@ using DecimalMath; +using InnovEnergy.Lib.Units.Generator; using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Units; -using T = Angle; - -public readonly struct Angle +[Generate] +public readonly partial struct Angle { - - public static String Unit => "rad"; public static String Symbol => "∠"; public static readonly Angle Pi = new Angle(DecimalEx.Pi); - public Decimal Value { get; } public Angle(Decimal value) { @@ -24,50 +21,5 @@ public readonly struct Angle ? modulo - DecimalEx.TwoPi : modulo; } - - public override String ToString() => Value + Unit; - - - #region scalar multiplication - - public static Angle operator *(Decimal scalar, Angle angle ) => new Angle(scalar * angle.Value); - public static Angle operator *(Angle angle , Decimal scalar) => new Angle(scalar * angle.Value); - public static Angle operator /(Angle angle , Decimal scalar) => new Angle(angle.Value / scalar); - - #endregion - - #region addition - - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); - public static T operator -(T t) => new T(-t.Value); - - #endregion - - #region compare - - public static Boolean operator ==(T left, T right) => left.Value == right.Value; - public static Boolean operator !=(T left, T right) => left.Value != right.Value; - public static Boolean operator > (T left, T right) => left.Value > right.Value; - public static Boolean operator < (T left, T right) => left.Value < right.Value; - public static Boolean operator >=(T left, T right) => left.Value >= right.Value; - public static Boolean operator <=(T left, T right) => left.Value <= right.Value; - - #endregion - - #region conversion - - public static implicit operator T(Decimal d) => new T(d); - public static implicit operator T(Double d) => new T((Decimal)d); - public static implicit operator T(Int32 i) => new T(i); - public static implicit operator Decimal(T t) => t.Value; - - #endregion - - #region equality - - public override Boolean Equals(Object? obj) => obj is T other && Equals(other); - public override Int32 GetHashCode() => Value.GetHashCode(); - - #endregion + } \ No newline at end of file diff --git a/csharp/Lib/Units/ApparentPower.cs b/csharp/Lib/Units/ApparentPower.cs new file mode 100644 index 000000000..b2a5bba6c --- /dev/null +++ b/csharp/Lib/Units/ApparentPower.cs @@ -0,0 +1,16 @@ +using InnovEnergy.Lib.Units.Generator; + +namespace InnovEnergy.Lib.Units; + +[Generate] +public readonly partial struct ApparentPower +{ + public static String Unit => "VA"; + public static String Symbol => "S"; + + public ApparentPower(Decimal value) + { + if (value < 0) throw new ArgumentException("Apparent power cannot be negative", nameof(value)); + Value = value; + } +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/Ac1Phase.cs b/csharp/Lib/Units/Composite/Ac1Phase.cs index e9970378b..00f823791 100644 --- a/csharp/Lib/Units/Composite/Ac1Phase.cs +++ b/csharp/Lib/Units/Composite/Ac1Phase.cs @@ -1,10 +1,10 @@ namespace InnovEnergy.Lib.Units.Composite; public record Ac1Phase - ( - Voltage Voltage, - Current Current, - Angle Phi, - Frequency Frequency - ) : - AcPhase(Voltage, Current, Phi); \ No newline at end of file +( + Voltage Voltage, + Current Current, + Angle Phi, + Frequency Frequency +) : +AcPhase(Voltage, Current, Phi); \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/Ac3Phase.cs b/csharp/Lib/Units/Composite/Ac3Phase.cs index 1fc44306f..be4f7c73d 100644 --- a/csharp/Lib/Units/Composite/Ac3Phase.cs +++ b/csharp/Lib/Units/Composite/Ac3Phase.cs @@ -1,8 +1,12 @@ +using static DecimalMath.DecimalEx; + namespace InnovEnergy.Lib.Units.Composite; public record Ac3Phase(AcPhase L1, AcPhase L2, AcPhase L3, Decimal Frequency) { - public Power ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; - public Power ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; - public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; + public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; + public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; + public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; + + public Angle Phi => ATan2(ReactivePower, ActivePower); } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/AcPhase.cs b/csharp/Lib/Units/Composite/AcPhase.cs index c616b9c57..f194f28af 100644 --- a/csharp/Lib/Units/Composite/AcPhase.cs +++ b/csharp/Lib/Units/Composite/AcPhase.cs @@ -5,7 +5,7 @@ namespace InnovEnergy.Lib.Units.Composite; public record AcPhase : Phase { - protected AcPhase(Voltage voltage, Current current, Angle phi) : base(voltage, current) + public AcPhase(Voltage voltage, Current current, Angle phi) : base(voltage, current) { if (voltage < 0) throw new ArgumentException("RMS value cannot be negative", nameof(voltage)); if (current < 0) throw new ArgumentException("RMS value cannot be negative", nameof(current)); @@ -15,8 +15,8 @@ public record AcPhase : Phase public Angle Phi { get; } - public Power ApparentPower => Voltage * Current; - public Power ActivePower => ApparentPower * PowerFactor; - public Power ReactivePower => ApparentPower * Sin(Phi); - public Decimal PowerFactor => Cos(Phi); + public ApparentPower ApparentPower => Math.Abs(Voltage.Value * Current.Value) ; + public Power ActivePower => ApparentPower.Value * PowerFactor; + public ReactivePower ReactivePower => ApparentPower.Value * Sin(Phi); + public Decimal PowerFactor => Cos(Phi); } \ No newline at end of file diff --git a/csharp/Lib/Units/Frequency.cs b/csharp/Lib/Units/Frequency.cs index 91a3e3849..173f5037d 100644 --- a/csharp/Lib/Units/Frequency.cs +++ b/csharp/Lib/Units/Frequency.cs @@ -1,59 +1,13 @@ +using InnovEnergy.Lib.Units.Generator; + namespace InnovEnergy.Lib.Units; -using T = Frequency; -public readonly struct Frequency +[Generate] +public readonly partial struct Frequency { public static String Unit => "Hz"; public static String Symbol => "f"; - public Decimal Value { get; } - public Frequency(Decimal value) => Value = value; - - public override String ToString() => Value + Unit; - - #region scalar multiplication - - public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); - public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); - public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - - #endregion - - #region addition - - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); - public static T operator -(T t) => new T(-t.Value); - - #endregion - - #region compare - - public static Boolean operator ==(T left, T right) => left.Value == right.Value; - public static Boolean operator !=(T left, T right) => left.Value != right.Value; - public static Boolean operator > (T left, T right) => left.Value > right.Value; - public static Boolean operator < (T left, T right) => left.Value < right.Value; - public static Boolean operator >=(T left, T right) => left.Value >= right.Value; - public static Boolean operator <=(T left, T right) => left.Value <= right.Value; - - #endregion - - #region conversion - - public static implicit operator T(Decimal d) => new T(d); - public static implicit operator T(Double d) => new T((Decimal)d); - public static implicit operator T(Int32 i) => new T(i); - public static implicit operator Decimal(T t) => t.Value; - - #endregion - - #region equality - - public Boolean Equals(T other) => Value == other.Value; - public override Boolean Equals(Object? obj) => obj is T other && Equals(other); - public override Int32 GetHashCode() => Value.GetHashCode(); - - #endregion } \ No newline at end of file diff --git a/csharp/Lib/Units/Generator/GenerateAttribute.cs b/csharp/Lib/Units/Generator/GenerateAttribute.cs new file mode 100644 index 000000000..c6643d2d7 --- /dev/null +++ b/csharp/Lib/Units/Generator/GenerateAttribute.cs @@ -0,0 +1,5 @@ +namespace InnovEnergy.Lib.Units.Generator; + +[AttributeUsage(AttributeTargets.Struct)] +internal class GenerateAttribute: Attribute +{} \ No newline at end of file diff --git a/csharp/Lib/Units/Generator/Template.txt b/csharp/Lib/Units/Generator/Template.txt new file mode 100644 index 000000000..6055ace01 --- /dev/null +++ b/csharp/Lib/Units/Generator/Template.txt @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Template; + +public readonly partial struct Template +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} diff --git a/csharp/Lib/Units/Generator/generate.sh b/csharp/Lib/Units/Generator/generate.sh new file mode 100755 index 000000000..01ff06f64 --- /dev/null +++ b/csharp/Lib/Units/Generator/generate.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + + +scriptDir=$( dirname -- "$0"; ) +cd "$scriptDir/.." || exit + +for file in $(grep -l '\[Generate\]' *.cs) +do + filename=$(basename -- "$file") + class="${filename%.*}" + echo "generating $filename" + sed "s/Template/$class/g" "./Generator/Template.txt" > "./$class.generated.cs" +done \ No newline at end of file diff --git a/csharp/Lib/Units/Power.cs b/csharp/Lib/Units/Power.cs index 4bc44a53a..716336a5e 100644 --- a/csharp/Lib/Units/Power.cs +++ b/csharp/Lib/Units/Power.cs @@ -1,66 +1,19 @@ +using InnovEnergy.Lib.Units.Generator; + namespace InnovEnergy.Lib.Units; -using T = Power; - -public readonly struct Power +[Generate] +public readonly partial struct Power { public static String Unit => "W"; public static String Symbol => "P"; - - public Decimal Value { get; } public Power(Decimal value) => Value = value; - public override String ToString() => Value + Unit; - // P=UI public static Voltage operator /(Power power, Current current) => new Voltage(power.Value / current.Value); public static Current operator /(Power power, Voltage voltage) => new Current(power.Value / voltage.Value); - #region scalar multiplication - - public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); - public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); - public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - - #endregion - - #region addition - - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); - public static T operator -(T t) => new T(-t.Value); - - #endregion - - #region compare - - public static Boolean operator ==(T left, T right) => left.Value == right.Value; - public static Boolean operator !=(T left, T right) => left.Value != right.Value; - public static Boolean operator > (T left, T right) => left.Value > right.Value; - public static Boolean operator < (T left, T right) => left.Value < right.Value; - public static Boolean operator >=(T left, T right) => left.Value >= right.Value; - public static Boolean operator <=(T left, T right) => left.Value <= right.Value; - - #endregion - - #region conversion - - public static implicit operator T(Decimal d) => new T(d); - public static implicit operator T(Double d) => new T((Decimal)d); - public static implicit operator T(Int32 i) => new T(i); - public static implicit operator Decimal(T t) => t.Value; - - #endregion - - #region equality - - public Boolean Equals(T other) => Value == other.Value; - public override Boolean Equals(Object? obj) => obj is T other && Equals(other); - public override Int32 GetHashCode() => Value.GetHashCode(); - - #endregion - } \ No newline at end of file diff --git a/csharp/Lib/Units/Power.generated.cs b/csharp/Lib/Units/Power.generated.cs new file mode 100644 index 000000000..3d4d12a65 --- /dev/null +++ b/csharp/Lib/Units/Power.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = ReactivePower; + +public readonly partial struct ReactivePower +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/ReactivePower.cs b/csharp/Lib/Units/ReactivePower.cs new file mode 100644 index 000000000..a7017cb32 --- /dev/null +++ b/csharp/Lib/Units/ReactivePower.cs @@ -0,0 +1,13 @@ + +using InnovEnergy.Lib.Units.Generator; + +namespace InnovEnergy.Lib.Units; + +[Generate] +public readonly partial struct ReactivePower +{ + public static String Unit => "var"; + public static String Symbol => "Q"; + + public ReactivePower(Decimal value) => Value = value; +} \ No newline at end of file diff --git a/csharp/Lib/Units/Resistance.cs b/csharp/Lib/Units/Resistance.cs index c3c0b34c0..f31cd4a4b 100644 --- a/csharp/Lib/Units/Resistance.cs +++ b/csharp/Lib/Units/Resistance.cs @@ -1,63 +1,19 @@ +using InnovEnergy.Lib.Units.Generator; + namespace InnovEnergy.Lib.Units; -using T = Resistance; - -public readonly struct Resistance +[Generate] +public readonly partial struct Resistance { public static String Unit => "Ω"; public static String Symbol => "R"; - public Decimal Value { get; } public Resistance(Decimal value) => Value = value; - public override String ToString() => Value + Unit; - // U=RI public static Voltage operator *(Resistance resistance, Current current) => new Voltage(resistance.Value * current.Value); - #region scalar multiplication - - public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); - public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); - public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - - #endregion - - #region addition - - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); - public static T operator -(T t) => new T(-t.Value); - - #endregion - - #region compare - - public static Boolean operator ==(T left, T right) => left.Value == right.Value; - public static Boolean operator !=(T left, T right) => left.Value != right.Value; - public static Boolean operator > (T left, T right) => left.Value > right.Value; - public static Boolean operator < (T left, T right) => left.Value < right.Value; - public static Boolean operator >=(T left, T right) => left.Value >= right.Value; - public static Boolean operator <=(T left, T right) => left.Value <= right.Value; - - #endregion - - #region conversion - - public static implicit operator T(Decimal d) => new T(d); - public static implicit operator T(Double d) => new T((Decimal)d); - public static implicit operator T(Int32 i) => new T(i); - public static implicit operator Decimal(T t) => t.Value; - - #endregion - - #region equality - - public Boolean Equals(T other) => Value == other.Value; - public override Boolean Equals(Object? obj) => obj is T other && Equals(other); - public override Int32 GetHashCode() => Value.GetHashCode(); - - #endregion + } \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.cs b/csharp/Lib/Units/Temperature.cs index 22a411338..243487d7f 100644 --- a/csharp/Lib/Units/Temperature.cs +++ b/csharp/Lib/Units/Temperature.cs @@ -1,61 +1,12 @@ +using InnovEnergy.Lib.Units.Generator; + namespace InnovEnergy.Lib.Units; -using T = Temperature; - -public readonly struct Temperature +[Generate] +public readonly partial struct Temperature { public static String Unit => "°C"; public static String Symbol => "T"; - public Decimal Value { get; } - public Temperature(Decimal value) => Value = value; - - public override String ToString() => Value + Unit; - - - #region scalar multiplication - - public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); - public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); - public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - - #endregion - - #region addition - - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); - public static T operator -(T t) => new T(-t.Value); - - #endregion - - #region compare - - public static Boolean operator ==(T left, T right) => left.Value == right.Value; - public static Boolean operator !=(T left, T right) => left.Value != right.Value; - public static Boolean operator > (T left, T right) => left.Value > right.Value; - public static Boolean operator < (T left, T right) => left.Value < right.Value; - public static Boolean operator >=(T left, T right) => left.Value >= right.Value; - public static Boolean operator <=(T left, T right) => left.Value <= right.Value; - - #endregion - - #region conversion - - public static implicit operator T(Decimal d) => new T(d); - public static implicit operator T(Double d) => new T((Decimal)d); - public static implicit operator T(Int32 i) => new T(i); - public static implicit operator Decimal(T t) => t.Value; - - #endregion - - #region equality - - public Boolean Equals(T other) => Value == other.Value; - public override Boolean Equals(Object? obj) => obj is T other && Equals(other); - public override Int32 GetHashCode() => Value.GetHashCode(); - - #endregion - } \ No newline at end of file diff --git a/csharp/Lib/Units/Units.cs b/csharp/Lib/Units/Units.cs index 88b9e04aa..de1b246ad 100644 --- a/csharp/Lib/Units/Units.cs +++ b/csharp/Lib/Units/Units.cs @@ -5,16 +5,23 @@ namespace InnovEnergy.Lib.Units; public static class Units { - public static Current A (this Decimal value) => new Current(value); - public static Voltage V (this Decimal value) => new Voltage(value); - public static Power W (this Decimal value) => new Power(value); - public static Resistance Ohm(this Decimal value) => new Resistance(value); + public static Current A (this Decimal value) => new Current(value); + public static Voltage V (this Decimal value) => new Voltage(value); + public static Power W (this Decimal value) => new Power(value); + public static ReactivePower Var (this Decimal value) => new ReactivePower(value); + public static ApparentPower Va (this Decimal value) => new ApparentPower(value); + public static Resistance Ohm (this Decimal value) => new Resistance(value); + public static Frequency Hz (this Decimal value) => new Frequency(value); + public static Angle Rad (this Decimal value) => new Angle(value); + public static Temperature Celsius(this Decimal value) => new Temperature(value); public static readonly IReadOnlyList JsonConverters = new JsonConverter[] { new CurrentConverter(), new VoltageConverter(), new PowerConverter(), - new ResistanceConverter() + new ResistanceConverter(), + + // TODO }; } \ No newline at end of file diff --git a/csharp/Lib/Units/Units.csproj b/csharp/Lib/Units/Units.csproj index eab4f3f58..4cedc809f 100644 --- a/csharp/Lib/Units/Units.csproj +++ b/csharp/Lib/Units/Units.csproj @@ -1,11 +1,6 @@ - - Library - preview - - @@ -14,4 +9,8 @@ + + + + diff --git a/csharp/Lib/Units/Voltage.cs b/csharp/Lib/Units/Voltage.cs index db75e63e0..5bbfc088f 100644 --- a/csharp/Lib/Units/Voltage.cs +++ b/csharp/Lib/Units/Voltage.cs @@ -1,69 +1,19 @@ +using InnovEnergy.Lib.Units.Generator; + namespace InnovEnergy.Lib.Units; -using T = Voltage; - -public readonly struct Voltage +[Generate] +public readonly partial struct Voltage { public static String Unit => "V"; public static String Symbol => "U"; - - public Decimal Value { get; } public Voltage(Decimal value) => Value = value; - public override String ToString() => Value + Unit; // U=RI public static Current operator /(Voltage voltage, Resistance resistance) => new Current(voltage.Value / resistance.Value); // P=UI public static Power operator *(Voltage voltage, Current current) => new Power(current.Value * voltage.Value); - - - #region scalar multiplication - - public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); - public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); - public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - - #endregion - - #region addition - - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); - public static T operator -(T t) => new T(-t.Value); - - #endregion - - #region compare - - public static Boolean operator ==(T left, T right) => left.Value == right.Value; - public static Boolean operator !=(T left, T right) => left.Value != right.Value; - public static Boolean operator > (T left, T right) => left.Value > right.Value; - public static Boolean operator < (T left, T right) => left.Value < right.Value; - public static Boolean operator >=(T left, T right) => left.Value >= right.Value; - public static Boolean operator <=(T left, T right) => left.Value <= right.Value; - - #endregion - - #region conversion - - public static implicit operator T(Decimal d) => new T(d); - public static implicit operator T(Double d) => new T((Decimal)d); - public static implicit operator T(Int32 i) => new T(i); - public static implicit operator Decimal(T t) => t.Value; - - #endregion - - #region equality - - public Boolean Equals(T other) => Value == other.Value; - public override Boolean Equals(Object? obj) => obj is T other && Equals(other); - public override Int32 GetHashCode() => Value.GetHashCode(); - - #endregion - - - } \ No newline at end of file From e74d94e268998a5a13116e396abcbb377d515c3e Mon Sep 17 00:00:00 2001 From: ig Date: Sun, 26 Feb 2023 15:43:53 +0100 Subject: [PATCH 017/114] Add missing .generated.cs files. --- csharp/InnovEnergy.sln | 1 + csharp/Lib/Units/Angle.generated.cs | 46 +++++++++++++++++++++ csharp/Lib/Units/Current.cs | 20 +++++++++ csharp/Lib/Units/Current.generated.cs | 46 +++++++++++++++++++++ csharp/Lib/Units/Frequency.generated.cs | 46 +++++++++++++++++++++ csharp/Lib/Units/ReactivePower.generated.cs | 46 +++++++++++++++++++++ csharp/Lib/Units/Resistance.generated.cs | 46 +++++++++++++++++++++ csharp/Lib/Units/Temperature.generated.cs | 46 +++++++++++++++++++++ csharp/Lib/Units/Voltage.generated.cs | 46 +++++++++++++++++++++ 9 files changed, 343 insertions(+) create mode 100644 csharp/Lib/Units/Angle.generated.cs create mode 100644 csharp/Lib/Units/Current.cs create mode 100644 csharp/Lib/Units/Current.generated.cs create mode 100644 csharp/Lib/Units/Frequency.generated.cs create mode 100644 csharp/Lib/Units/ReactivePower.generated.cs create mode 100644 csharp/Lib/Units/Resistance.generated.cs create mode 100644 csharp/Lib/Units/Temperature.generated.cs create mode 100644 csharp/Lib/Units/Voltage.generated.cs diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 3a0fa6fcd..8d368b9cb 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -69,6 +69,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Meta", "Meta", "{AED84693-C App\InnovEnergy.App.props = App\InnovEnergy.App.props Lib\InnovEnergy.Lib.props = Lib\InnovEnergy.Lib.props InnovEnergy.sln.DotSettings = InnovEnergy.sln.DotSettings + ..\.gitignore = ..\.gitignore EndProjectSection EndProject diff --git a/csharp/Lib/Units/Angle.generated.cs b/csharp/Lib/Units/Angle.generated.cs new file mode 100644 index 000000000..77f634fd3 --- /dev/null +++ b/csharp/Lib/Units/Angle.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Angle; + +public readonly partial struct Angle +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Current.cs b/csharp/Lib/Units/Current.cs new file mode 100644 index 000000000..d2d674d04 --- /dev/null +++ b/csharp/Lib/Units/Current.cs @@ -0,0 +1,20 @@ +using InnovEnergy.Lib.Units.Generator; + +namespace InnovEnergy.Lib.Units; + + +[Generate] +public readonly partial struct Current +{ + public static String Unit => "A"; + public static String Symbol => "I"; + + public Current(Decimal value) => Value = value; + + // P=UI + public static Power operator *(Current current, Voltage voltage) => new Power(current.Value * voltage.Value); + + // U=RI + public static Voltage operator *(Current current, Resistance resistance) => new Voltage(resistance.Value* current.Value); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Current.generated.cs b/csharp/Lib/Units/Current.generated.cs new file mode 100644 index 000000000..bc1964810 --- /dev/null +++ b/csharp/Lib/Units/Current.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Current; + +public readonly partial struct Current +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Frequency.generated.cs b/csharp/Lib/Units/Frequency.generated.cs new file mode 100644 index 000000000..2959bdbc4 --- /dev/null +++ b/csharp/Lib/Units/Frequency.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Frequency; + +public readonly partial struct Frequency +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/ReactivePower.generated.cs b/csharp/Lib/Units/ReactivePower.generated.cs new file mode 100644 index 000000000..20a55cccc --- /dev/null +++ b/csharp/Lib/Units/ReactivePower.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Power; + +public readonly partial struct Power +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Resistance.generated.cs b/csharp/Lib/Units/Resistance.generated.cs new file mode 100644 index 000000000..9a715bf51 --- /dev/null +++ b/csharp/Lib/Units/Resistance.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Resistance; + +public readonly partial struct Resistance +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.generated.cs b/csharp/Lib/Units/Temperature.generated.cs new file mode 100644 index 000000000..1c87f4c31 --- /dev/null +++ b/csharp/Lib/Units/Temperature.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Temperature; + +public readonly partial struct Temperature +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file diff --git a/csharp/Lib/Units/Voltage.generated.cs b/csharp/Lib/Units/Voltage.generated.cs new file mode 100644 index 000000000..d64264d60 --- /dev/null +++ b/csharp/Lib/Units/Voltage.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = Voltage; + +public readonly partial struct Voltage +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file From d2bef311c01ce031a2cea411833f9492195e87a0 Mon Sep 17 00:00:00 2001 From: ig Date: Sun, 26 Feb 2023 15:59:55 +0100 Subject: [PATCH 018/114] Add missing .generated.cs files. --- csharp/Lib/Units/ApparentPower.generated.cs | 46 +++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 csharp/Lib/Units/ApparentPower.generated.cs diff --git a/csharp/Lib/Units/ApparentPower.generated.cs b/csharp/Lib/Units/ApparentPower.generated.cs new file mode 100644 index 000000000..f413a8811 --- /dev/null +++ b/csharp/Lib/Units/ApparentPower.generated.cs @@ -0,0 +1,46 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. + +namespace InnovEnergy.Lib.Units; + +using T = ApparentPower; + +public readonly partial struct ApparentPower +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // addition + + public static T operator +(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator -(T t) => new T(-t.Value); + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} \ No newline at end of file From d5c523974425c94e73d9ce2216d339f29bcfe9ad Mon Sep 17 00:00:00 2001 From: ig Date: Sun, 26 Feb 2023 19:19:16 +0100 Subject: [PATCH 019/114] implement operator + for all Units --- csharp/Lib/Units/Angle.cs | 2 +- csharp/Lib/Units/Angle.generated.cs | 36 ++++++++++++++++- csharp/Lib/Units/ApparentPower.cs | 2 +- csharp/Lib/Units/ApparentPower.generated.cs | 36 ++++++++++++++++- csharp/Lib/Units/Composite/Ac1Phase.cs | 26 +++++++++--- csharp/Lib/Units/Composite/Ac3Phase.cs | 15 ++++++- csharp/Lib/Units/Composite/AcPhase.cs | 34 +++++++++++++++- csharp/Lib/Units/Composite/DcPhase.cs | 9 +++++ csharp/Lib/Units/Current.cs | 2 +- csharp/Lib/Units/Current.generated.cs | 36 ++++++++++++++++- csharp/Lib/Units/Frequency.cs | 11 +++-- csharp/Lib/Units/Frequency.generated.cs | 36 ++++++++++++++++- ...GenerateAttribute.cs => EqualAttribute.cs} | 2 +- csharp/Lib/Units/Generator/MeanAttribute.cs | 5 +++ csharp/Lib/Units/Generator/SumAttribute.cs | 5 +++ csharp/Lib/Units/Generator/Template.txt | 34 +++++++++++++++- csharp/Lib/Units/Generator/generate.sh | 12 +++--- csharp/Lib/Units/Power.cs | 2 +- csharp/Lib/Units/Power.generated.cs | 40 +++++++++++++++++-- csharp/Lib/Units/ReactivePower.cs | 2 +- csharp/Lib/Units/ReactivePower.generated.cs | 40 +++++++++++++++++-- csharp/Lib/Units/Resistance.cs | 4 +- csharp/Lib/Units/Resistance.generated.cs | 36 ++++++++++++++++- csharp/Lib/Units/Temperature.cs | 6 ++- csharp/Lib/Units/Temperature.generated.cs | 36 ++++++++++++++++- csharp/Lib/Units/Voltage.cs | 2 +- csharp/Lib/Units/Voltage.generated.cs | 36 ++++++++++++++++- 27 files changed, 458 insertions(+), 49 deletions(-) rename csharp/Lib/Units/Generator/{GenerateAttribute.cs => EqualAttribute.cs} (65%) create mode 100644 csharp/Lib/Units/Generator/MeanAttribute.cs create mode 100644 csharp/Lib/Units/Generator/SumAttribute.cs diff --git a/csharp/Lib/Units/Angle.cs b/csharp/Lib/Units/Angle.cs index 87a3ed2b4..b8972c826 100644 --- a/csharp/Lib/Units/Angle.cs +++ b/csharp/Lib/Units/Angle.cs @@ -4,7 +4,7 @@ using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Units; -[Generate] +[Sum] public readonly partial struct Angle { public static String Unit => "rad"; diff --git a/csharp/Lib/Units/Angle.generated.cs b/csharp/Lib/Units/Angle.generated.cs index 77f634fd3..ad576594a 100644 --- a/csharp/Lib/Units/Angle.generated.cs +++ b/csharp/Lib/Units/Angle.generated.cs @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct Angle public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct Angle public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/ApparentPower.cs b/csharp/Lib/Units/ApparentPower.cs index b2a5bba6c..8c92385de 100644 --- a/csharp/Lib/Units/ApparentPower.cs +++ b/csharp/Lib/Units/ApparentPower.cs @@ -2,7 +2,7 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; -[Generate] +[Sum] public readonly partial struct ApparentPower { public static String Unit => "VA"; diff --git a/csharp/Lib/Units/ApparentPower.generated.cs b/csharp/Lib/Units/ApparentPower.generated.cs index f413a8811..cfa6174ed 100644 --- a/csharp/Lib/Units/ApparentPower.generated.cs +++ b/csharp/Lib/Units/ApparentPower.generated.cs @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct ApparentPower public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct ApparentPower public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/Composite/Ac1Phase.cs b/csharp/Lib/Units/Composite/Ac1Phase.cs index 00f823791..e48807866 100644 --- a/csharp/Lib/Units/Composite/Ac1Phase.cs +++ b/csharp/Lib/Units/Composite/Ac1Phase.cs @@ -1,10 +1,26 @@ +using System.Diagnostics.CodeAnalysis; + namespace InnovEnergy.Lib.Units.Composite; public record Ac1Phase ( - Voltage Voltage, - Current Current, - Angle Phi, + Voltage Voltage, + Current Current, + Angle Phi, Frequency Frequency -) : -AcPhase(Voltage, Current, Phi); \ No newline at end of file +) + : AcPhase(Voltage, Current, Phi) +{ + + [SuppressMessage("ReSharper", "RedundantCast")] + public static Ac1Phase operator +(Ac1Phase left, Ac1Phase right) + { + var f = (left.Frequency + right.Frequency) / 2m; // TODO: check that l & r approximately equal + var acPhase = (AcPhase)left + (AcPhase)right; + return new Ac1Phase(acPhase.Voltage, acPhase.Current, acPhase.Phi, f); + } + +} + + + diff --git a/csharp/Lib/Units/Composite/Ac3Phase.cs b/csharp/Lib/Units/Composite/Ac3Phase.cs index be4f7c73d..a5788e452 100644 --- a/csharp/Lib/Units/Composite/Ac3Phase.cs +++ b/csharp/Lib/Units/Composite/Ac3Phase.cs @@ -2,11 +2,24 @@ using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Units.Composite; -public record Ac3Phase(AcPhase L1, AcPhase L2, AcPhase L3, Decimal Frequency) +public record Ac3Phase(AcPhase L1, AcPhase L2, AcPhase L3, Frequency Frequency) { public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; public Angle Phi => ATan2(ReactivePower, ActivePower); + + + public static Ac3Phase operator +(Ac3Phase left, Ac3Phase right) + { + var f = (left.Frequency + right.Frequency) / 2m; // TODO: check that l & r approximately equal + + var l1 = left.L1 + right.L1; + var l2 = left.L2 + right.L2; + var l3 = left.L3 + right.L3; + + return new Ac3Phase(l1, l2, l3, f); + } + } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/AcPhase.cs b/csharp/Lib/Units/Composite/AcPhase.cs index f194f28af..70cd952b2 100644 --- a/csharp/Lib/Units/Composite/AcPhase.cs +++ b/csharp/Lib/Units/Composite/AcPhase.cs @@ -15,8 +15,40 @@ public record AcPhase : Phase public Angle Phi { get; } - public ApparentPower ApparentPower => Math.Abs(Voltage.Value * Current.Value) ; + public ApparentPower ApparentPower => Voltage.Value * Current.Value ; public Power ActivePower => ApparentPower.Value * PowerFactor; public ReactivePower ReactivePower => ApparentPower.Value * Sin(Phi); public Decimal PowerFactor => Cos(Phi); + + + public static AcPhase operator +(AcPhase left, AcPhase right) + { + // the Voltages of two phases are expected to be in phase and equal + + var v = (left.Voltage + right.Voltage) / 2m; // TODO: check that l & r approximately equal + + // currents (RMS) can be different and out of phase + // https://www.johndcook.com/blog/2020/08/17/adding-phase-shifted-sine-waves/ + + // IF + // left(t) = ILeft sin(ωt) + // right(t) = IRight sin(ωt + φ). + // sum(t) = left(t) + right(t) = ISum sin(ωt + ψ). + // THEN + + // ψ = arctan( IRight * sin(φ) / (ILeft + IRight cos(φ)) ). + // C = IRight * sin(φ) / sin(ψ). + + // in this calc left(t) has zero phase shift. + // we can shift both waves by -left.Phi, so + // φ := right.phi - left.phi + + + var phi = right.Phi - left.Phi; + + var phiSum = ATan2(right.Current * Sin(phi), left.Current + right.Current * Cos(phi)); + var iSum = right.Current * Sin(phi) / Sin(phiSum); + + return new AcPhase(v, iSum, phiSum); + } } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/DcPhase.cs b/csharp/Lib/Units/Composite/DcPhase.cs index 8e73313bf..af6d1049a 100644 --- a/csharp/Lib/Units/Composite/DcPhase.cs +++ b/csharp/Lib/Units/Composite/DcPhase.cs @@ -3,4 +3,13 @@ namespace InnovEnergy.Lib.Units.Composite; public record DcPhase(Voltage Voltage, Current Current) : Phase(Voltage, Current) { public Power Power => Current * Voltage; + + public static DcPhase operator +(DcPhase left, DcPhase right) + { + var v = (left.Voltage + right.Voltage) / 2m; + var i = left.Current + right.Current; + + return new DcPhase(v, i); + } + } \ No newline at end of file diff --git a/csharp/Lib/Units/Current.cs b/csharp/Lib/Units/Current.cs index d2d674d04..b3c36ee34 100644 --- a/csharp/Lib/Units/Current.cs +++ b/csharp/Lib/Units/Current.cs @@ -3,7 +3,7 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; -[Generate] +[Sum] public readonly partial struct Current { public static String Unit => "A"; diff --git a/csharp/Lib/Units/Current.generated.cs b/csharp/Lib/Units/Current.generated.cs index bc1964810..cda7eeadf 100644 --- a/csharp/Lib/Units/Current.generated.cs +++ b/csharp/Lib/Units/Current.generated.cs @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct Current public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct Current public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/Frequency.cs b/csharp/Lib/Units/Frequency.cs index 173f5037d..3041325c2 100644 --- a/csharp/Lib/Units/Frequency.cs +++ b/csharp/Lib/Units/Frequency.cs @@ -2,12 +2,17 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; - -[Generate] +[Equal] public readonly partial struct Frequency { public static String Unit => "Hz"; public static String Symbol => "f"; - public Frequency(Decimal value) => Value = value; + public Frequency(Decimal value) + { + if (value < 0) + throw new ArgumentException(nameof(Frequency) + " cannot be negative", nameof(value)); + + Value = value; + } } \ No newline at end of file diff --git a/csharp/Lib/Units/Frequency.generated.cs b/csharp/Lib/Units/Frequency.generated.cs index 2959bdbc4..015d67536 100644 --- a/csharp/Lib/Units/Frequency.generated.cs +++ b/csharp/Lib/Units/Frequency.generated.cs @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Equal + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct Frequency public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct Frequency public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/Generator/GenerateAttribute.cs b/csharp/Lib/Units/Generator/EqualAttribute.cs similarity index 65% rename from csharp/Lib/Units/Generator/GenerateAttribute.cs rename to csharp/Lib/Units/Generator/EqualAttribute.cs index c6643d2d7..c0131044a 100644 --- a/csharp/Lib/Units/Generator/GenerateAttribute.cs +++ b/csharp/Lib/Units/Generator/EqualAttribute.cs @@ -1,5 +1,5 @@ namespace InnovEnergy.Lib.Units.Generator; [AttributeUsage(AttributeTargets.Struct)] -internal class GenerateAttribute: Attribute +internal class EqualAttribute: Attribute {} \ No newline at end of file diff --git a/csharp/Lib/Units/Generator/MeanAttribute.cs b/csharp/Lib/Units/Generator/MeanAttribute.cs new file mode 100644 index 000000000..161da8b0e --- /dev/null +++ b/csharp/Lib/Units/Generator/MeanAttribute.cs @@ -0,0 +1,5 @@ +namespace InnovEnergy.Lib.Units.Generator; + +[AttributeUsage(AttributeTargets.Struct)] +internal class MeanAttribute: Attribute +{} \ No newline at end of file diff --git a/csharp/Lib/Units/Generator/SumAttribute.cs b/csharp/Lib/Units/Generator/SumAttribute.cs new file mode 100644 index 000000000..c4af9a156 --- /dev/null +++ b/csharp/Lib/Units/Generator/SumAttribute.cs @@ -0,0 +1,5 @@ +namespace InnovEnergy.Lib.Units.Generator; + +[AttributeUsage(AttributeTargets.Struct)] +internal class SumAttribute: Attribute +{} \ No newline at end of file diff --git a/csharp/Lib/Units/Generator/Template.txt b/csharp/Lib/Units/Generator/Template.txt index 6055ace01..c656f51df 100644 --- a/csharp/Lib/Units/Generator/Template.txt +++ b/csharp/Lib/Units/Generator/Template.txt @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Type + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct Template public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare diff --git a/csharp/Lib/Units/Generator/generate.sh b/csharp/Lib/Units/Generator/generate.sh index 01ff06f64..625f32f89 100755 --- a/csharp/Lib/Units/Generator/generate.sh +++ b/csharp/Lib/Units/Generator/generate.sh @@ -4,10 +4,12 @@ scriptDir=$( dirname -- "$0"; ) cd "$scriptDir/.." || exit -for file in $(grep -l '\[Generate\]' *.cs) +for match in $(grep -e '\[Sum\]\|\[Equal\]\|\[Mean\]' -o *.cs | tr -d '[]') do - filename=$(basename -- "$file") - class="${filename%.*}" - echo "generating $filename" - sed "s/Template/$class/g" "./Generator/Template.txt" > "./$class.generated.cs" + path="${match%:*}" + type="${match#*:}" + file=$(basename -- "$path") + class="${file%.*}" + echo "generating $file" + sed "s/Template/$class/g; s/Type/$type/" "./Generator/Template.txt" > "./$class.generated.cs" done \ No newline at end of file diff --git a/csharp/Lib/Units/Power.cs b/csharp/Lib/Units/Power.cs index 716336a5e..eaedbf7f2 100644 --- a/csharp/Lib/Units/Power.cs +++ b/csharp/Lib/Units/Power.cs @@ -3,7 +3,7 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; -[Generate] +[Sum] public readonly partial struct Power { public static String Unit => "W"; diff --git a/csharp/Lib/Units/Power.generated.cs b/csharp/Lib/Units/Power.generated.cs index 3d4d12a65..c26ad26fd 100644 --- a/csharp/Lib/Units/Power.generated.cs +++ b/csharp/Lib/Units/Power.generated.cs @@ -1,10 +1,13 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; namespace InnovEnergy.Lib.Units; -using T = ReactivePower; +using T = Power; -public readonly partial struct ReactivePower +public readonly partial struct Power { public Decimal Value { get; } public override String ToString() => Value + Unit; @@ -16,10 +19,39 @@ public readonly partial struct ReactivePower public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct ReactivePower public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/ReactivePower.cs b/csharp/Lib/Units/ReactivePower.cs index a7017cb32..30d7641b9 100644 --- a/csharp/Lib/Units/ReactivePower.cs +++ b/csharp/Lib/Units/ReactivePower.cs @@ -3,7 +3,7 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; -[Generate] +[Sum] public readonly partial struct ReactivePower { public static String Unit => "var"; diff --git a/csharp/Lib/Units/ReactivePower.generated.cs b/csharp/Lib/Units/ReactivePower.generated.cs index 20a55cccc..9b8def505 100644 --- a/csharp/Lib/Units/ReactivePower.generated.cs +++ b/csharp/Lib/Units/ReactivePower.generated.cs @@ -1,10 +1,13 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; namespace InnovEnergy.Lib.Units; -using T = Power; +using T = ReactivePower; -public readonly partial struct Power +public readonly partial struct ReactivePower { public Decimal Value { get; } public override String ToString() => Value + Unit; @@ -16,10 +19,39 @@ public readonly partial struct Power public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct Power public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/Resistance.cs b/csharp/Lib/Units/Resistance.cs index f31cd4a4b..ce426e229 100644 --- a/csharp/Lib/Units/Resistance.cs +++ b/csharp/Lib/Units/Resistance.cs @@ -2,7 +2,7 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; -[Generate] +[Sum] public readonly partial struct Resistance { public static String Unit => "Ω"; @@ -13,7 +13,5 @@ public readonly partial struct Resistance // U=RI public static Voltage operator *(Resistance resistance, Current current) => new Voltage(resistance.Value * current.Value); - - } \ No newline at end of file diff --git a/csharp/Lib/Units/Resistance.generated.cs b/csharp/Lib/Units/Resistance.generated.cs index 9a715bf51..5be7685b6 100644 --- a/csharp/Lib/Units/Resistance.generated.cs +++ b/csharp/Lib/Units/Resistance.generated.cs @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct Resistance public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct Resistance public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/Temperature.cs b/csharp/Lib/Units/Temperature.cs index 243487d7f..dc2d7e5ad 100644 --- a/csharp/Lib/Units/Temperature.cs +++ b/csharp/Lib/Units/Temperature.cs @@ -2,11 +2,15 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; -[Generate] +using T=Temperature; + +[Mean] public readonly partial struct Temperature { public static String Unit => "°C"; public static String Symbol => "T"; public Temperature(Decimal value) => Value = value; + + } \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.generated.cs b/csharp/Lib/Units/Temperature.generated.cs index 1c87f4c31..edc3fdbfa 100644 --- a/csharp/Lib/Units/Temperature.generated.cs +++ b/csharp/Lib/Units/Temperature.generated.cs @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Mean + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct Temperature public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct Temperature public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} diff --git a/csharp/Lib/Units/Voltage.cs b/csharp/Lib/Units/Voltage.cs index 5bbfc088f..2c65129e4 100644 --- a/csharp/Lib/Units/Voltage.cs +++ b/csharp/Lib/Units/Voltage.cs @@ -2,7 +2,7 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; -[Generate] +[Equal] public readonly partial struct Voltage { public static String Unit => "V"; diff --git a/csharp/Lib/Units/Voltage.generated.cs b/csharp/Lib/Units/Voltage.generated.cs index d64264d60..07dc88d06 100644 --- a/csharp/Lib/Units/Voltage.generated.cs +++ b/csharp/Lib/Units/Voltage.generated.cs @@ -1,4 +1,7 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Equal + +using static System.Math; namespace InnovEnergy.Lib.Units; @@ -16,10 +19,39 @@ public readonly partial struct Voltage public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); // addition - + + #if Sum + public static T operator +(T left, T right) => new T(left.Value + right.Value); public static T operator -(T left, T right) => new T(left.Value - right.Value); public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator +(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d != 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif // compare @@ -43,4 +75,4 @@ public readonly partial struct Voltage public override Boolean Equals(Object? obj) => obj is T other && Equals(other); public override Int32 GetHashCode() => Value.GetHashCode(); -} \ No newline at end of file +} From 476a0a0fe2e8633e98943026369a75ecd08909a6 Mon Sep 17 00:00:00 2001 From: ig Date: Sun, 26 Feb 2023 19:20:43 +0100 Subject: [PATCH 020/114] rename Ac1 in IAc1Connection to plain Ac --- .../StatusApi/Connections/IAc1Connection.cs | 2 +- csharp/Lib/StatusApi/DeviceStatus.cs | 19 +++++++------------ .../StatusApi/SinglePhaseInverterStatus.cs | 2 +- .../StatusApi/SinglePhasePvInverterStatus.cs | 2 +- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/csharp/Lib/StatusApi/Connections/IAc1Connection.cs b/csharp/Lib/StatusApi/Connections/IAc1Connection.cs index df3a472a1..d90b57938 100644 --- a/csharp/Lib/StatusApi/Connections/IAc1Connection.cs +++ b/csharp/Lib/StatusApi/Connections/IAc1Connection.cs @@ -4,5 +4,5 @@ namespace InnovEnergy.Lib.StatusApi.Connections; public interface IAc1Connection { - Ac1Phase Ac1 { get; } + Ac1Phase Ac { get; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/DeviceStatus.cs b/csharp/Lib/StatusApi/DeviceStatus.cs index f34a37d23..6cdc1ef3f 100644 --- a/csharp/Lib/StatusApi/DeviceStatus.cs +++ b/csharp/Lib/StatusApi/DeviceStatus.cs @@ -1,17 +1,12 @@ +using InnovEnergy.Lib.Utils; + namespace InnovEnergy.Lib.StatusApi; public abstract record DeviceStatus { - public String DeviceType - { - get - { - var t = GetType(); - - while (!t!.IsAbstract) - t = t.BaseType; - - return t.Name.Replace("Status", ""); - } - } + public String DeviceType => GetType() + .Generate(t => t.BaseType!) + .First(t => t.IsAbstract) + .Name + .Replace("Status", ""); } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs index a1b404bd6..9e1e2c8ba 100644 --- a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs @@ -3,7 +3,7 @@ using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record SinglePhaseInverterStatus(Ac1Phase Ac1, DcPhase Dc) : +public abstract record SinglePhaseInverterStatus(Ac1Phase Ac, DcPhase Dc) : DeviceStatus, IAc1Connection, IDcConnection; diff --git a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs index 377f9f6f3..51c113fce 100644 --- a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs @@ -3,7 +3,7 @@ using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record SinglePhasePvInverterStatus(Ac1Phase Ac1, IReadOnlyList Strings) : +public abstract record SinglePhasePvInverterStatus(Ac1Phase Ac, IReadOnlyList Strings) : DeviceStatus, IAc1Connection, IPvConnection; From 3795385ccb651edf0ae99e27b247a137994d6f56 Mon Sep 17 00:00:00 2001 From: Kim Date: Tue, 28 Feb 2023 08:27:59 +0100 Subject: [PATCH 021/114] Remove Spaces --- doc/controller_tests/controller_tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/controller_tests/controller_tests.md b/doc/controller_tests/controller_tests.md index e4dbda5d5..b7f1d2a0c 100644 --- a/doc/controller_tests/controller_tests.md +++ b/doc/controller_tests/controller_tests.md @@ -17,6 +17,6 @@ Unless noted otherwise, these procedures assume a test system with a single batt 9. [Hold min SOC -> Optimize Self-Consumption](Hold min SOC -> Optimize Self-Consumption.md) 10. [Forced EOC -> Bridge Grid Blackout -> Forced EOC](Forced EOC -> Bridge Grid Blackout -> Forced EOC.md) 11. [Optimize Self-Consumption -> Bridge Grid Blackout -> Charge to min SOC -> Hold min SOC](Optimize Self-Consumption -> Bridge Grid Blackout -> Charge to min SOC -> Hold min SOC.md) -12. [Disconnect Grid Meter](Disconnect Grid Meter.md) +12. [Disconnect Grid Meter](DisconnectGridMeter.md) 13. [Optimize Self-Consumption -> Limit Discharge Power](Optimize Self-Consumption -> Limit Discharge Power.md) 14. [Limit Charge Power -> Optimize Self-Consumption](Limit Charge Power -> Optimize Self-Consumption.md) From 6edba78845a0cc52158de9fa05fe639ff5e27d83 Mon Sep 17 00:00:00 2001 From: Sina Blattmann Date: Tue, 28 Feb 2023 11:06:26 +0100 Subject: [PATCH 022/114] fix nested routing, create tree with data from backend --- typescript/Frontend/src/App.tsx | 58 ++------- .../src/components/InstallationList.tsx | 50 ++++---- .../src/components/InstallationTabs.tsx | 20 ++-- .../src/components/NavigationButtons.tsx | 30 ++--- .../Frontend/src/components/UserTree.tsx | 112 +++--------------- typescript/Frontend/src/routes.json | 15 +-- .../Frontend/src/routes/Installation.tsx | 2 +- .../Frontend/src/routes/Installations.tsx | 49 ++++++++ typescript/Frontend/src/routes/Users.tsx | 30 +++++ 9 files changed, 168 insertions(+), 198 deletions(-) create mode 100644 typescript/Frontend/src/routes/Installations.tsx create mode 100644 typescript/Frontend/src/routes/Users.tsx diff --git a/typescript/Frontend/src/App.tsx b/typescript/Frontend/src/App.tsx index 711216363..5a482cdda 100644 --- a/typescript/Frontend/src/App.tsx +++ b/typescript/Frontend/src/App.tsx @@ -1,12 +1,7 @@ import useToken from "./hooks/useToken"; import Login from "./Login"; import { BrowserRouter, Route, Routes } from "react-router-dom"; -import { Box, Grid, Divider } from "@mui/material"; -import BasicTable from "./components/Table"; -import InstallationTabs from "./components/InstallationTabs"; -import Alarms from "./routes/Alarms"; -import InstallationDetail from "./routes/Installation"; -import Log from "./routes/Log"; +import { Grid } from "@mui/material"; import routes from "./routes.json"; import { IntlProvider } from "react-intl"; import { useState } from "react"; @@ -14,14 +9,13 @@ import en from "./lang/en.json"; import de from "./lang/de.json"; import LanguageSelect from "./components/LanguageSelect"; import LogoutButton from "./components/LogoutButton"; -import NavigationButtons from "./components/NavigationButtons"; -import UserList from "./components/UserTree"; -import Sidebar from "./components/Sidebar"; +import Installations from "./routes/Installations"; + +import Users from "./routes/Users"; const App = () => { const { token, setToken, removeToken } = useToken(); const [language, setLanguage] = useState("en"); - const [currentView, setCurrentView] = useState("installations"); const getTranslations = () => { if (language === "de") { @@ -45,43 +39,13 @@ const App = () => { - - - - - {currentView === "installations" ? : } - - - - - - {currentView === "installations" && ( - <> - - - } - /> - } /> - } /> - } /> - - - )} - - - + + } + /> + } /> + ); diff --git a/typescript/Frontend/src/components/InstallationList.tsx b/typescript/Frontend/src/components/InstallationList.tsx index c151fd9aa..07ff648fe 100644 --- a/typescript/Frontend/src/components/InstallationList.tsx +++ b/typescript/Frontend/src/components/InstallationList.tsx @@ -41,10 +41,10 @@ const InstallationList = (props: InstallationListProps) => { const filteredData = filterData(props.searchQuery, data); const routeMatch = useRouteMatch([ - routes.installationWithId, - routes.alarmsWithId, - routes.usersWithId, - routes.logWithId, + routes.installations + routes.installation + ":id", + routes.installations + routes.alarms + ":id", + routes.installations + routes.users + ":id", + routes.installations + routes.log + ":id", ]); useEffect(() => { @@ -76,25 +76,31 @@ const InstallationList = (props: InstallationListProps) => { component="nav" aria-labelledby="nested-list-subheader" > - {filteredData?.map((installation) => ( - - - { + console.log(routeMatch); + return ( + + - - - - - - ))} + + + + + + + ); + })} )} diff --git a/typescript/Frontend/src/components/InstallationTabs.tsx b/typescript/Frontend/src/components/InstallationTabs.tsx index 8291357ac..86987e375 100644 --- a/typescript/Frontend/src/components/InstallationTabs.tsx +++ b/typescript/Frontend/src/components/InstallationTabs.tsx @@ -9,10 +9,10 @@ import { useIntl } from "react-intl"; const InstallationTabs = () => { const routeMatch = useRouteMatch([ - routes.installationWithId, - routes.alarmsWithId, - routes.usersWithId, - routes.logWithId, + routes.installations + routes.installation + ":id", + routes.installations + routes.alarms + ":id", + routes.installations + routes.users + ":id", + routes.installations + routes.log + ":id", ]); const id = routeMatch?.params?.id; @@ -23,7 +23,7 @@ const InstallationTabs = () => { { id: "installation", defaultMessage: "Installation", })} - value={routes.installationWithId} + value={ + routes.installations + routes.installation + ":id" + } component={Link} to={routes.installation + id} /> @@ -40,7 +42,7 @@ const InstallationTabs = () => { id: "alarms", defaultMessage: "Alarms", })} - value={routes.alarmsWithId} + value={routes.installations + routes.alarms + ":id"} component={Link} to={routes.alarms + id} /> @@ -49,7 +51,7 @@ const InstallationTabs = () => { id: "users", defaultMessage: "Users", })} - value={routes.usersWithId} + value={routes.installations + routes.users + ":id"} component={Link} to={routes.users + id} /> @@ -58,7 +60,7 @@ const InstallationTabs = () => { id: "log", defaultMessage: "Log", })} - value={routes.logWithId} + value={routes.installations + routes.log + ":id"} component={Link} to={routes.log + id} /> diff --git a/typescript/Frontend/src/components/NavigationButtons.tsx b/typescript/Frontend/src/components/NavigationButtons.tsx index 21ccbde9a..096061cb0 100644 --- a/typescript/Frontend/src/components/NavigationButtons.tsx +++ b/typescript/Frontend/src/components/NavigationButtons.tsx @@ -1,33 +1,33 @@ import { ToggleButton, ToggleButtonGroup } from "@mui/material"; import { FormattedMessage } from "react-intl"; +import { Link } from "react-router-dom"; +import useRouteMatch from "../hooks/useRouteMatch"; +import routes from "../routes.json"; -interface NavigationButtonsProps { - currentView: string; - setCurrentView: (value: string) => void; -} -const NavigationButtons = (props: NavigationButtonsProps) => { - const handleChange = ( - event: React.MouseEvent, - newAlignment: string - ) => { - props.setCurrentView(newAlignment); - }; +const NavigationButtons = () => { + const routeMatch = useRouteMatch([ + routes.installations + "*", + routes.tree + "*", + ]); return ( - + - + diff --git a/typescript/Frontend/src/components/UserTree.tsx b/typescript/Frontend/src/components/UserTree.tsx index 219b2e8ca..0e9a7694a 100644 --- a/typescript/Frontend/src/components/UserTree.tsx +++ b/typescript/Frontend/src/components/UserTree.tsx @@ -1,102 +1,23 @@ import TreeView from "@mui/lab/TreeView"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; -import { ReactNode } from "react"; +import { ReactNode, useEffect, useState } from "react"; import { TreeItem } from "@mui/lab"; import { I_Folder, I_Installation } from "../util/types"; +import axiosConfig from "../config/axiosConfig"; const UserList = () => { - const data: I_Folder[] = [ - { - id: 107, - name: "Bruen-Tromp", - information: "05 Burrows Terrace", - parentId: 75, - type: "Folder", - children: [ - { - id: 100, - name: "Sporer and Sons", - information: "820 Helena Terrace", - parentId: 107, - type: "Folder", - }, - { - id: 101, - name: "Hahn-Heaney", - information: "144 Di Loreto Center", - parentId: 107, - type: "Folder", - }, - ], - }, - { - id: 125, - name: "Sporer and Sons", - information: "820 Helena Terrace", - parentId: 107, - type: "Folder", - children: [ - { - location: "Säffle", - region: "SG", - country: "SE", - orderNumbers: "1LWDGmdXCLmCRFJHTKwcmpoP7bcNeaWJuj", - lat: 0, - long: 0, - s3Bucket: "", - id: 632, - name: "Nikolas Scholz", - information: "", - parentId: 125, - type: "Installation", - }, - { - location: "Krasnoye", - region: "ZH", - country: "RU", - orderNumbers: "1M4Rw8toMSJn3d8ULouDd1gYKzANFXeMWh", - lat: 0, - long: 0, - s3Bucket: "", - id: 248, - name: "Judye Goldson", - information: "", - parentId: 125, - type: "Installation", - }, - { - id: 103, - name: "Bruen-Tromp", - information: "05 Burrows Terrace", - parentId: 75, - type: "Folder", - children: [ - { - id: 100, - name: "Sporer and Sons", - information: "820 Helena Terrace", - parentId: 107, - type: "Folder", - }, - { - id: 101, - name: "Hahn-Heaney", - information: "144 Di Loreto Center", - parentId: 107, - type: "Folder", - }, - ], - }, - ], - }, - { - id: 135, - name: "Hahn-Heaney", - information: "144 Di Loreto Center", - parentId: 107, - type: "Folder", - }, - ]; + const [data, setData] = useState(); + + useEffect(() => { + axiosConfig.get("/GetTree").then((res) => { + setData(res.data); + }); + }, []); + + const handleClick = (e: any, nodes: any) => { + console.log(e); + console.log(nodes); + }; const instanceOfFolder = (object: any): object is I_Folder => { return "children" in object; @@ -122,14 +43,15 @@ const UserList = () => { ); }); }; + return ( } defaultExpandIcon={} sx={{ height: 300, flexGrow: 1, maxWidth: 400 }} + onNodeToggle={handleClick} > - {renderTree(data)} + {data && renderTree(data)} ); }; diff --git a/typescript/Frontend/src/routes.json b/typescript/Frontend/src/routes.json index 311ef8a1c..c65eb635d 100644 --- a/typescript/Frontend/src/routes.json +++ b/typescript/Frontend/src/routes.json @@ -1,11 +1,8 @@ { - "installationWithId": "/installation/:id", - "installation": "/installation/", - "alarmsWithId": "/alarms/:id", - "alarms": "/alarms/", - "usersWithId": "/users/:id", - "users": "/users/", - "logWithId": "/log/:id", - "log": "/log/", - "installations": "/installations" + "installation": "installation/", + "alarms": "alarms/", + "users": "users/", + "log": "log/", + "installations": "/installations/", + "tree": "/users/*" } diff --git a/typescript/Frontend/src/routes/Installation.tsx b/typescript/Frontend/src/routes/Installation.tsx index 675d65ca7..fe6c60dac 100644 --- a/typescript/Frontend/src/routes/Installation.tsx +++ b/typescript/Frontend/src/routes/Installation.tsx @@ -28,7 +28,7 @@ const InstallationDetail = () => { if (values && values.id && values.id.toString() === id) { return ( - + ); diff --git a/typescript/Frontend/src/routes/Installations.tsx b/typescript/Frontend/src/routes/Installations.tsx new file mode 100644 index 000000000..f412a2934 --- /dev/null +++ b/typescript/Frontend/src/routes/Installations.tsx @@ -0,0 +1,49 @@ +import { Grid, Divider } from "@mui/material"; +import { Container } from "@mui/system"; +import { Routes, Route } from "react-router"; +import InstallationTabs from "../components/InstallationTabs"; +import NavigationButtons from "../components/NavigationButtons"; +import BasicTable from "../components/Table"; +import Alarms from "./Alarms"; +import InstallationDetail from "./Installation"; +import Log from "./Log"; +import routes from "../routes.json"; +import Sidebar from "../components/Sidebar"; + +const Installations = () => { + return ( + + + + + + + + + + + + + } + index + /> + } /> + } /> + } /> + + + + + ); +}; + +export default Installations; diff --git a/typescript/Frontend/src/routes/Users.tsx b/typescript/Frontend/src/routes/Users.tsx new file mode 100644 index 000000000..472c949e8 --- /dev/null +++ b/typescript/Frontend/src/routes/Users.tsx @@ -0,0 +1,30 @@ +import { Grid, Divider } from "@mui/material"; +import { Container } from "@mui/system"; +import NavigationButtons from "../components/NavigationButtons"; +import UserTree from "../components/UserTree"; + +const Users = () => { + return ( + + + + + + + + + + + + + ); +}; + +export default Users; From 45e12b031835dce518f7a543175e6ff7636ef9be Mon Sep 17 00:00:00 2001 From: Kim Date: Tue, 28 Feb 2023 11:16:19 +0100 Subject: [PATCH 023/114] added method to create new s3 keys for users --- csharp/App/Backend/Database/User.cs | 34 ++++++++++++++++------------ csharp/App/Backend/db.sqlite | Bin 290816 -> 290816 bytes 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/csharp/App/Backend/Database/User.cs b/csharp/App/Backend/Database/User.cs index e002c48be..77897bffd 100644 --- a/csharp/App/Backend/Database/User.cs +++ b/csharp/App/Backend/Database/User.cs @@ -1,6 +1,9 @@ +using System.Diagnostics.CodeAnalysis; using System.Net.Mail; using System.Security.Cryptography; using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; using Flurl.Http; using Innovenergy.Backend.Model; using Innovenergy.Backend.Utils; @@ -56,38 +59,41 @@ public partial class Db return Create(user); } + [UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")] public Object CreateAndSaveUserS3ApiKey(User user) { //EXOSCALE API URL const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0"; const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; - var payload = new - { - name = user.Email, - operations = new List { "getObject", "listBucket" }, - content = new List { } - }; - var installationIdList = User2Installation + var installationList = User2Installation .Where(i => i.UserId == user.Id) .SelectMany(i => Installations.Where(f => i.InstallationId == f.Id)) .ToList(); - foreach (var installation in installationIdList) + + var instList = new JsonArray(); + + foreach (var installation in installationList) { - payload.content.Add(new { domain = "sos", resource_type = "bucket", resource_name = installation.Name }); //TODO CHANGE NAME TO S3BUCKET + instList.Add(new JsonObject {["domain"] = "sos",["resource-name"] = installation.Name,["resource-type"] = "bucket"}); } - + + var jsonPayload = new JsonObject { ["name"] = user.Email, ["operations"] = new JsonArray{ "getObject", "listBucket" }, ["content"] = instList}; + var expiration = DateTime.Now.AddHours(24); + + var signature = $"POST /v2/access-key\n{jsonPayload}\n\n\n{expiration}"; using var hmacSha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret)); - var signature = Encoding.UTF8 - .GetBytes(payload.ToString()) + + signature = Encoding.UTF8 + .GetBytes(signature) .Apply(hmacSha1.ComputeHash) .Apply(Convert.ToBase64String); var keyJson = url - .WithHeader("Authorization", $"POST {apiKey};{signature}") - .PostJsonAsync(payload) + .WithHeader("Authorization", $"EXO2-HMAC-SHA256 credential={apiKey},expires={((DateTimeOffset)expiration).ToUnixTimeSeconds()},signature={signature}") + .PostJsonAsync(jsonPayload.ToString()) .ReceiveJson() .Result; diff --git a/csharp/App/Backend/db.sqlite b/csharp/App/Backend/db.sqlite index 982a3ab9194e88a44231a09570b7baa0be6f249f..ce3c81c14b45c6aad65fe4c712c1c0ebc1cbb3c9 100644 GIT binary patch delta 102769 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

ql^<|&*8R8L2br28plJmtnN?s{H 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%0A24=nK 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

eG>jBT^4U9iisB!n-Y&C?h7~Zez`2& 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

wx4f`QV|7Xo8 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 M=AyLVn5cRG1CB_Lpa1{> From 69fed10f69573edb3b86e3a7e3f9c82cd5e77700 Mon Sep 17 00:00:00 2001 From: Kim Date: Tue, 28 Feb 2023 12:34:36 +0100 Subject: [PATCH 024/114] wip debugging the s3 key generation --- csharp/App/Backend/Database/User.cs | 19 +++++++++++-------- csharp/App/Backend/db.sqlite | Bin 290816 -> 290816 bytes 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/csharp/App/Backend/Database/User.cs b/csharp/App/Backend/Database/User.cs index 77897bffd..ea2344aaf 100644 --- a/csharp/App/Backend/Database/User.cs +++ b/csharp/App/Backend/Database/User.cs @@ -81,23 +81,26 @@ public partial class Db } var jsonPayload = new JsonObject { ["name"] = user.Email, ["operations"] = new JsonArray{ "getObject", "listBucket" }, ["content"] = instList}; - var expiration = DateTime.Now.AddHours(24); + var expiration = DateTime.Now.AddSeconds(60); - var signature = $"POST /v2/access-key\n{jsonPayload}\n\n\n{expiration}"; - using var hmacSha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret)); + var signature = $"POST /v2/access-key\n{jsonPayload}\n\n\n{((DateTimeOffset)expiration).ToUnixTimeSeconds()}"; + using var hmacSha256 = new HMACSHA256(Encoding.UTF8.GetBytes(secret)); signature = Encoding.UTF8 .GetBytes(signature) - .Apply(hmacSha1.ComputeHash) + .Apply(hmacSha256.ComputeHash) .Apply(Convert.ToBase64String); var keyJson = url - .WithHeader("Authorization", $"EXO2-HMAC-SHA256 credential={apiKey},expires={((DateTimeOffset)expiration).ToUnixTimeSeconds()},signature={signature}") - .PostJsonAsync(jsonPayload.ToString()) + .WithHeader("Authorization", + $"EXO2-HMAC-SHA256 credential={apiKey},expires={((DateTimeOffset)expiration).ToUnixTimeSeconds()},signature={signature}"); + + + var result = keyJson.PostJsonAsync(jsonPayload.ToString()) .ReceiveJson() .Result; - - return SetUserS3ApiKey(user, keyJson.GetValue("key")); + return result; + // return SetUserS3ApiKey(user, keyJson.GetValue("key")); } public Result SetUserS3ApiKey(User user, String key) diff --git a/csharp/App/Backend/db.sqlite b/csharp/App/Backend/db.sqlite index ce3c81c14b45c6aad65fe4c712c1c0ebc1cbb3c9..92600a4864c5a88b620d6123ca5b78f4b298c2b9 100644 GIT binary patch delta 94744 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 From 3758165c08d0c4d38fa4920860a0410a649123a4 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:02:49 +0100 Subject: [PATCH 025/114] fix RootNamespace for Apps --- csharp/App/InnovEnergy.App.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/App/InnovEnergy.App.props b/csharp/App/InnovEnergy.App.props index 38d62f4dc..fe6d1e334 100644 --- a/csharp/App/InnovEnergy.App.props +++ b/csharp/App/InnovEnergy.App.props @@ -19,7 +19,7 @@ Exe - InnovEnergy.App.$(AssemblyName) + \ No newline at end of file From a32cf8389312e8e672fd1d4f04256478c315b9c9 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:04:53 +0100 Subject: [PATCH 026/114] add CreateBinaryOpForProps --- csharp/Lib/Utils/Operators.cs | 95 +++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 csharp/Lib/Utils/Operators.cs diff --git a/csharp/Lib/Utils/Operators.cs b/csharp/Lib/Utils/Operators.cs new file mode 100644 index 000000000..644cb2906 --- /dev/null +++ b/csharp/Lib/Utils/Operators.cs @@ -0,0 +1,95 @@ +using System.Reflection; +using static System.Reflection.BindingFlags; + +namespace InnovEnergy.Lib.Utils; + +public static class Operators +{ + public static Func CreateBinaryOpForProps(this String op) + { + var methodName = GetMethodNameForBinaryOp(op); + + var props = typeof(T) + .GetProperties(Instance | Public) + .Where(p => p.CanWrite) + .Select(p => + ( + prop: p, + op: GetOpMethod(methodName, p.PropertyType) ?? + throw new ArgumentException($"Type {p.PropertyType.Name} " + + $"of property {p.Name} " + + $"has no suitable {op} operator defined.")) + ) + .ToArray(); + + var ctr = typeof(T).GetConstructors().FirstOrDefault(c => c.GetParameters().Length == 0); + + if (ctr is null) + throw new ArgumentException($"Type {typeof(T).Name} has no suitable parameterless constructor."); + + + T Op(T left, T right) + { + // TODO: make this faster/nicer using Expression API (low prio) + + var result = ctr.Invoke(null); + + foreach (var (p, m) in props) + { + var l = p.GetValue(left); + var r = p.GetValue(right); + + var s = m.Invoke(null, new[] { l, r }); + + p.SetValue(result, s); + } + + return (T) result; + } + + return Op; + } + + private static String GetMethodNameForBinaryOp(String op) + { + // from https://stackoverflow.com/a/29495075 + + return op switch + { + "&" => "op_BitwiseAnd", + "|" => "op_BitwiseOr", + "+" => "op_Addition", + "-" => "op_Subtraction", + "/" => "op_Division", + "%" => "op_Modulus", + "*" => "op_Multiply", + "<<" => "op_LeftShift", + ">>" => "op_RightShift", + "^" => "op_ExclusiveOr", + "==" => "op_Equality", + "!=" => "op_Inequality", + ">" => "op_GreaterThan", + "<" => "op_LessThan", + ">=" => "op_GreaterThanOrEqual", + "<=" => "op_LessThanOrEqual", + _ => throw new ArgumentException("unknown operator", nameof(op)) + }; + } + + private static MethodInfo? GetOpMethod(String? methodName, Type type) + { + return type + .GetMethods(Static | Public) + .FirstOrDefault(m => m.Name == methodName + && m.ReturnType == type + && m.IsMonoidOp()); + } + + private static Boolean IsMonoidOp(this MethodInfo m) + { + var ps = m.GetParameters(); + + return ps.Length == 2 && + ps.All(p => p.ParameterType == m.ReturnType); + } +} \ No newline at end of file From 2070fce4eccb89c2ece58f10a6de07ecb5b9adaa Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:05:57 +0100 Subject: [PATCH 027/114] implement | (parallel) operator for all Units --- csharp/Lib/Units/Angle.generated.cs | 11 +++--- csharp/Lib/Units/ApparentPower.generated.cs | 11 +++--- csharp/Lib/Units/Composite/Ac1Phase.cs | 27 +++++++------ csharp/Lib/Units/Composite/Ac3Phase.cs | 23 +++++------ csharp/Lib/Units/Composite/AcPhase.cs | 44 +++++++++++++-------- csharp/Lib/Units/Composite/DcPhase.cs | 21 +++++----- csharp/Lib/Units/Composite/IPhase.cs | 11 ++++++ csharp/Lib/Units/Composite/Phase.cs | 7 ---- csharp/Lib/Units/Current.generated.cs | 11 +++--- csharp/Lib/Units/Frequency.generated.cs | 11 +++--- csharp/Lib/Units/Generator/Template.txt | 11 +++--- csharp/Lib/Units/Power.generated.cs | 11 +++--- csharp/Lib/Units/ReactivePower.generated.cs | 11 +++--- csharp/Lib/Units/Resistance.cs | 3 ++ csharp/Lib/Units/Resistance.generated.cs | 11 +++--- csharp/Lib/Units/State.cs | 2 +- csharp/Lib/Units/Temperature.cs | 1 - csharp/Lib/Units/Temperature.generated.cs | 11 +++--- csharp/Lib/Units/Units.cs | 2 + csharp/Lib/Units/Voltage.generated.cs | 11 +++--- 20 files changed, 131 insertions(+), 120 deletions(-) create mode 100644 csharp/Lib/Units/Composite/IPhase.cs delete mode 100644 csharp/Lib/Units/Composite/Phase.cs diff --git a/csharp/Lib/Units/Angle.generated.cs b/csharp/Lib/Units/Angle.generated.cs index ad576594a..f2317f977 100644 --- a/csharp/Lib/Units/Angle.generated.cs +++ b/csharp/Lib/Units/Angle.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Angle public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/ApparentPower.generated.cs b/csharp/Lib/Units/ApparentPower.generated.cs index cfa6174ed..0775151c9 100644 --- a/csharp/Lib/Units/ApparentPower.generated.cs +++ b/csharp/Lib/Units/ApparentPower.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct ApparentPower public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Composite/Ac1Phase.cs b/csharp/Lib/Units/Composite/Ac1Phase.cs index e48807866..d7cfc20e7 100644 --- a/csharp/Lib/Units/Composite/Ac1Phase.cs +++ b/csharp/Lib/Units/Composite/Ac1Phase.cs @@ -1,25 +1,28 @@ + using System.Diagnostics.CodeAnalysis; namespace InnovEnergy.Lib.Units.Composite; -public record Ac1Phase -( - Voltage Voltage, - Current Current, - Angle Phi, - Frequency Frequency -) - : AcPhase(Voltage, Current, Phi) +public record Ac1Phase : AcPhase { + public required Frequency Frequency { get; init; } [SuppressMessage("ReSharper", "RedundantCast")] - public static Ac1Phase operator +(Ac1Phase left, Ac1Phase right) + public static Ac1Phase operator |(Ac1Phase left, Ac1Phase right) { - var f = (left.Frequency + right.Frequency) / 2m; // TODO: check that l & r approximately equal - var acPhase = (AcPhase)left + (AcPhase)right; - return new Ac1Phase(acPhase.Voltage, acPhase.Current, acPhase.Phi, f); + var f = left.Frequency | right.Frequency; + var p = (AcPhase)left | (AcPhase)right; + + return new Ac1Phase + { + Frequency = f, + Current = p.Current, + Voltage = p.Voltage, + Phi = p.Phi + }; } + } diff --git a/csharp/Lib/Units/Composite/Ac3Phase.cs b/csharp/Lib/Units/Composite/Ac3Phase.cs index a5788e452..d73f8e9e4 100644 --- a/csharp/Lib/Units/Composite/Ac3Phase.cs +++ b/csharp/Lib/Units/Composite/Ac3Phase.cs @@ -1,25 +1,22 @@ +using InnovEnergy.Lib.Utils; using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Units.Composite; -public record Ac3Phase(AcPhase L1, AcPhase L2, AcPhase L3, Frequency Frequency) +public record Ac3Phase { + public required AcPhase L1 { get; init; } + public required AcPhase L2 { get; init; } + public required AcPhase L3 { get; init; } + public required Frequency Frequency { get; init; } + public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; + public Angle Phi => ATan2(ReactivePower, ActivePower); - public Angle Phi => ATan2(ReactivePower, ActivePower); - - - public static Ac3Phase operator +(Ac3Phase left, Ac3Phase right) - { - var f = (left.Frequency + right.Frequency) / 2m; // TODO: check that l & r approximately equal + public static Ac3Phase operator |(Ac3Phase left, Ac3Phase right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); - var l1 = left.L1 + right.L1; - var l2 = left.L2 + right.L2; - var l3 = left.L3 + right.L3; - - return new Ac3Phase(l1, l2, l3, f); - } } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/AcPhase.cs b/csharp/Lib/Units/Composite/AcPhase.cs index 70cd952b2..426091fbc 100644 --- a/csharp/Lib/Units/Composite/AcPhase.cs +++ b/csharp/Lib/Units/Composite/AcPhase.cs @@ -3,17 +3,23 @@ using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Units.Composite; -public record AcPhase : Phase +public record AcPhase : IPhase { - public AcPhase(Voltage voltage, Current current, Angle phi) : base(voltage, current) + private readonly Voltage _Voltage; + public required Voltage Voltage { - if (voltage < 0) throw new ArgumentException("RMS value cannot be negative", nameof(voltage)); - if (current < 0) throw new ArgumentException("RMS value cannot be negative", nameof(current)); - - Phi = phi; + get => _Voltage; + init => _Voltage = value >= 0 ? value : throw new ArgumentException("RMS value cannot be negative"); } - public Angle Phi { get; } + private readonly Current _Current; + public required Current Current + { + get => _Current; + init => _Current = value >= 0 ? value : throw new ArgumentException("RMS value cannot be negative"); + } + + public required Angle Phi { get; init; } public ApparentPower ApparentPower => Voltage.Value * Current.Value ; public Power ActivePower => ApparentPower.Value * PowerFactor; @@ -21,34 +27,40 @@ public record AcPhase : Phase public Decimal PowerFactor => Cos(Phi); - public static AcPhase operator +(AcPhase left, AcPhase right) + public static AcPhase operator |(AcPhase left, AcPhase right) { // the Voltages of two phases are expected to be in phase and equal - var v = (left.Voltage + right.Voltage) / 2m; // TODO: check that l & r approximately equal + var v = left.Voltage | right.Voltage; // currents (RMS) can be different and out of phase // https://www.johndcook.com/blog/2020/08/17/adding-phase-shifted-sine-waves/ // IF - // left(t) = ILeft sin(ωt) + // left(t) = ILeft sin(ωt) // right(t) = IRight sin(ωt + φ). - // sum(t) = left(t) + right(t) = ISum sin(ωt + ψ). - // THEN + // sum(t) = left(t) + right(t) = ISum sin(ωt + ψ). + // THEN // ψ = arctan( IRight * sin(φ) / (ILeft + IRight cos(φ)) ). // C = IRight * sin(φ) / sin(ψ). - // in this calc left(t) has zero phase shift. + // in this calculation left(t) has zero phase shift. // we can shift both waves by -left.Phi, so // φ := right.phi - left.phi - var phi = right.Phi - left.Phi; - + var phi = right.Phi - left.Phi; var phiSum = ATan2(right.Current * Sin(phi), left.Current + right.Current * Cos(phi)); var iSum = right.Current * Sin(phi) / Sin(phiSum); - return new AcPhase(v, iSum, phiSum); + return new AcPhase + { + Voltage = v, + Current = iSum, + Phi = phiSum + }; } + + } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/DcPhase.cs b/csharp/Lib/Units/Composite/DcPhase.cs index af6d1049a..2d0b24b68 100644 --- a/csharp/Lib/Units/Composite/DcPhase.cs +++ b/csharp/Lib/Units/Composite/DcPhase.cs @@ -1,15 +1,16 @@ +using InnovEnergy.Lib.Utils; + namespace InnovEnergy.Lib.Units.Composite; -public record DcPhase(Voltage Voltage, Current Current) : Phase(Voltage, Current) +public record DcPhase : IPhase { - public Power Power => Current * Voltage; - - public static DcPhase operator +(DcPhase left, DcPhase right) - { - var v = (left.Voltage + right.Voltage) / 2m; - var i = left.Current + right.Current; - - return new DcPhase(v, i); - } + public required Voltage Voltage { get; init;} + public required Current Current { get; init;} + public Power Power => Current * Voltage; + + public static DcPhase operator |(DcPhase left, DcPhase right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + + } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/IPhase.cs b/csharp/Lib/Units/Composite/IPhase.cs new file mode 100644 index 000000000..b0ccfee66 --- /dev/null +++ b/csharp/Lib/Units/Composite/IPhase.cs @@ -0,0 +1,11 @@ +using System.Diagnostics.CodeAnalysis; + +namespace InnovEnergy.Lib.Units.Composite; + +[SuppressMessage("ReSharper", "MemberCanBeProtected.Global")] + +public interface IPhase +{ + public Voltage Voltage { get; } + public Current Current { get; } +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/Phase.cs b/csharp/Lib/Units/Composite/Phase.cs deleted file mode 100644 index 45a3ef86d..000000000 --- a/csharp/Lib/Units/Composite/Phase.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace InnovEnergy.Lib.Units.Composite; - -public abstract record Phase -( - Voltage Voltage, - Current Current -); \ No newline at end of file diff --git a/csharp/Lib/Units/Current.generated.cs b/csharp/Lib/Units/Current.generated.cs index cda7eeadf..93e9bdbf7 100644 --- a/csharp/Lib/Units/Current.generated.cs +++ b/csharp/Lib/Units/Current.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Current public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Frequency.generated.cs b/csharp/Lib/Units/Frequency.generated.cs index 015d67536..9618c18bc 100644 --- a/csharp/Lib/Units/Frequency.generated.cs +++ b/csharp/Lib/Units/Frequency.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Frequency public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Generator/Template.txt b/csharp/Lib/Units/Generator/Template.txt index c656f51df..c78a3fcc6 100644 --- a/csharp/Lib/Units/Generator/Template.txt +++ b/csharp/Lib/Units/Generator/Template.txt @@ -18,25 +18,24 @@ public readonly partial struct Template public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Power.generated.cs b/csharp/Lib/Units/Power.generated.cs index c26ad26fd..5ccca90ef 100644 --- a/csharp/Lib/Units/Power.generated.cs +++ b/csharp/Lib/Units/Power.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Power public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/ReactivePower.generated.cs b/csharp/Lib/Units/ReactivePower.generated.cs index 9b8def505..f438dd865 100644 --- a/csharp/Lib/Units/ReactivePower.generated.cs +++ b/csharp/Lib/Units/ReactivePower.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct ReactivePower public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Resistance.cs b/csharp/Lib/Units/Resistance.cs index ce426e229..ab0bc7bbe 100644 --- a/csharp/Lib/Units/Resistance.cs +++ b/csharp/Lib/Units/Resistance.cs @@ -2,6 +2,9 @@ using InnovEnergy.Lib.Units.Generator; namespace InnovEnergy.Lib.Units; + +// TODO: op parallel is wrong + [Sum] public readonly partial struct Resistance { diff --git a/csharp/Lib/Units/Resistance.generated.cs b/csharp/Lib/Units/Resistance.generated.cs index 5be7685b6..134384467 100644 --- a/csharp/Lib/Units/Resistance.generated.cs +++ b/csharp/Lib/Units/Resistance.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Resistance public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/State.cs b/csharp/Lib/Units/State.cs index 752a5751d..af96735e0 100644 --- a/csharp/Lib/Units/State.cs +++ b/csharp/Lib/Units/State.cs @@ -14,5 +14,5 @@ public readonly struct State public static implicit operator State(Enum e) => new State(e); public static implicit operator State(String s) => new State(s); - public static State operator +(State left, State right) => new State(left, right); + public static State operator |(State left, State right) => new State(left, right); } \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.cs b/csharp/Lib/Units/Temperature.cs index dc2d7e5ad..57e2406a3 100644 --- a/csharp/Lib/Units/Temperature.cs +++ b/csharp/Lib/Units/Temperature.cs @@ -11,6 +11,5 @@ public readonly partial struct Temperature public static String Symbol => "T"; public Temperature(Decimal value) => Value = value; - } \ No newline at end of file diff --git a/csharp/Lib/Units/Temperature.generated.cs b/csharp/Lib/Units/Temperature.generated.cs index edc3fdbfa..cc173ee61 100644 --- a/csharp/Lib/Units/Temperature.generated.cs +++ b/csharp/Lib/Units/Temperature.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Temperature public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; diff --git a/csharp/Lib/Units/Units.cs b/csharp/Lib/Units/Units.cs index de1b246ad..98bc153e8 100644 --- a/csharp/Lib/Units/Units.cs +++ b/csharp/Lib/Units/Units.cs @@ -5,6 +5,8 @@ namespace InnovEnergy.Lib.Units; public static class Units { + public const Decimal MaxRelativeError = 0.05m; // 5% + public static Current A (this Decimal value) => new Current(value); public static Voltage V (this Decimal value) => new Voltage(value); public static Power W (this Decimal value) => new Power(value); diff --git a/csharp/Lib/Units/Voltage.generated.cs b/csharp/Lib/Units/Voltage.generated.cs index 07dc88d06..cdb63dcda 100644 --- a/csharp/Lib/Units/Voltage.generated.cs +++ b/csharp/Lib/Units/Voltage.generated.cs @@ -18,25 +18,24 @@ public readonly partial struct Voltage public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); - // addition + // parallel #if Sum - public static T operator +(T left, T right) => new T(left.Value + right.Value); - public static T operator -(T left, T right) => new T(left.Value - right.Value); + public static T operator |(T left, T right) => new T(left.Value + right.Value); public static T operator -(T t) => new T(-t.Value); #elif Mean - public static T operator +(T left, T right) => new T((left.Value + right.Value)/2m); + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); #elif Equal - public static T operator +(T left, T right) + public static T operator |(T left, T right) { var d = Max(Abs(left.Value), Abs(right.Value)); - if (d != 0m) + if (d == 0m) return new T(0m); var relativeError = Abs(left.Value - right.Value) / d; From f1003c2877460cda807532b830031c6de4f462fb Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:07:26 +0100 Subject: [PATCH 028/114] implement | (parallel) operator in StatusApi.csproj --- csharp/InnovEnergy.sln.DotSettings | 1 + csharp/Lib/StatusApi/BatteryStatus.cs | 9 ++++++++- csharp/Lib/StatusApi/BatteryStatus.generated.cs | 16 ++++++++++++++++ .../Lib/StatusApi/Connections/IAc3Connection.cs | 2 +- csharp/Lib/StatusApi/DcDcConverterStatus.cs | 8 +++++++- .../StatusApi/DcDcConverterStatus.generated.cs | 16 ++++++++++++++++ .../StatusApi/Generator/OpParallelAttribute.cs | 5 +++++ csharp/Lib/StatusApi/Generator/Template.txt | 16 ++++++++++++++++ csharp/Lib/StatusApi/Generator/generate.sh | 13 +++++++++++++ csharp/Lib/StatusApi/MpptStatus.cs | 8 +++++++- csharp/Lib/StatusApi/MpptStatus.generated.cs | 16 ++++++++++++++++ csharp/Lib/StatusApi/PowerMeterStatus.cs | 7 ++++++- .../Lib/StatusApi/PowerMeterStatus.generated.cs | 16 ++++++++++++++++ .../Lib/StatusApi/SinglePhaseInverterStatus.cs | 10 ++++++++-- .../SinglePhaseInverterStatus.generated.cs | 16 ++++++++++++++++ .../Lib/StatusApi/SinglePhasePvInverterStatus.cs | 10 ++++++++-- .../SinglePhasePvInverterStatus.generated.cs | 16 ++++++++++++++++ csharp/Lib/StatusApi/StatusApi.csproj | 6 +++++- csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs | 10 ++++++++-- .../ThreePhaseInverterStatus.generated.cs | 16 ++++++++++++++++ .../Lib/StatusApi/ThreePhasePvInverterStatus.cs | 10 ++++++++-- .../ThreePhasePvInverterStatus.generated.cs | 16 ++++++++++++++++ csharp/Lib/StatusApi/Utils.cs | 11 ----------- 23 files changed, 229 insertions(+), 25 deletions(-) create mode 100644 csharp/Lib/StatusApi/BatteryStatus.generated.cs create mode 100644 csharp/Lib/StatusApi/DcDcConverterStatus.generated.cs create mode 100644 csharp/Lib/StatusApi/Generator/OpParallelAttribute.cs create mode 100644 csharp/Lib/StatusApi/Generator/Template.txt create mode 100755 csharp/Lib/StatusApi/Generator/generate.sh create mode 100644 csharp/Lib/StatusApi/MpptStatus.generated.cs create mode 100644 csharp/Lib/StatusApi/PowerMeterStatus.generated.cs create mode 100644 csharp/Lib/StatusApi/SinglePhaseInverterStatus.generated.cs create mode 100644 csharp/Lib/StatusApi/SinglePhasePvInverterStatus.generated.cs create mode 100644 csharp/Lib/StatusApi/ThreePhaseInverterStatus.generated.cs create mode 100644 csharp/Lib/StatusApi/ThreePhasePvInverterStatus.generated.cs delete mode 100644 csharp/Lib/StatusApi/Utils.cs diff --git a/csharp/InnovEnergy.sln.DotSettings b/csharp/InnovEnergy.sln.DotSettings index f48e450b2..0584ce254 100644 --- a/csharp/InnovEnergy.sln.DotSettings +++ b/csharp/InnovEnergy.sln.DotSettings @@ -4,6 +4,7 @@ False True + True True True True diff --git a/csharp/Lib/StatusApi/BatteryStatus.cs b/csharp/Lib/StatusApi/BatteryStatus.cs index 0b033b420..2e241e5a9 100644 --- a/csharp/Lib/StatusApi/BatteryStatus.cs +++ b/csharp/Lib/StatusApi/BatteryStatus.cs @@ -1,7 +1,14 @@ using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record BatteryStatus(DcPhase Dc) : DeviceStatus, IDcConnection; +using T = BatteryStatus; + +[OpParallel] +public partial record BatteryStatus : DeviceStatus, IDcConnection +{ + public required DcPhase Dc { get; init; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/BatteryStatus.generated.cs b/csharp/Lib/StatusApi/BatteryStatus.generated.cs new file mode 100644 index 000000000..d5f549056 --- /dev/null +++ b/csharp/Lib/StatusApi/BatteryStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = BatteryStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record BatteryStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IAc3Connection.cs b/csharp/Lib/StatusApi/Connections/IAc3Connection.cs index 231982cf0..b95939124 100644 --- a/csharp/Lib/StatusApi/Connections/IAc3Connection.cs +++ b/csharp/Lib/StatusApi/Connections/IAc3Connection.cs @@ -4,5 +4,5 @@ namespace InnovEnergy.Lib.StatusApi.Connections; public interface IAc3Connection { - Ac1Phase Ac3 { get; } + Ac3Phase Ac { get; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/DcDcConverterStatus.cs b/csharp/Lib/StatusApi/DcDcConverterStatus.cs index cdda395d9..a7d931065 100644 --- a/csharp/Lib/StatusApi/DcDcConverterStatus.cs +++ b/csharp/Lib/StatusApi/DcDcConverterStatus.cs @@ -1,8 +1,14 @@ +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record DcDcConverterStatus(DcPhase Left, DcPhase Right) : DeviceStatus; +[OpParallel] +public partial record DcDcConverterStatus : DeviceStatus +{ + public required DcPhase Left { get; init; } + public required DcPhase Right { get; init; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/DcDcConverterStatus.generated.cs b/csharp/Lib/StatusApi/DcDcConverterStatus.generated.cs new file mode 100644 index 000000000..32a133a8a --- /dev/null +++ b/csharp/Lib/StatusApi/DcDcConverterStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = DcDcConverterStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record DcDcConverterStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Generator/OpParallelAttribute.cs b/csharp/Lib/StatusApi/Generator/OpParallelAttribute.cs new file mode 100644 index 000000000..ec94f9d34 --- /dev/null +++ b/csharp/Lib/StatusApi/Generator/OpParallelAttribute.cs @@ -0,0 +1,5 @@ +namespace InnovEnergy.Lib.StatusApi.Generator; + +[AttributeUsage(AttributeTargets.Class)] +internal class OpParallelAttribute : Attribute +{} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Generator/Template.txt b/csharp/Lib/StatusApi/Generator/Template.txt new file mode 100644 index 000000000..43f22557f --- /dev/null +++ b/csharp/Lib/StatusApi/Generator/Template.txt @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = Template; + +[GeneratedCode("generate.sh", "1")] +public partial record Template +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Generator/generate.sh b/csharp/Lib/StatusApi/Generator/generate.sh new file mode 100755 index 000000000..1233bd1b7 --- /dev/null +++ b/csharp/Lib/StatusApi/Generator/generate.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + + +scriptDir=$( dirname -- "$0"; ) +cd "$scriptDir/.." || exit + +for path in $(grep -e '\[OpParallel\]' -l *.cs) +do + file=$(basename -- "$path") + class="${file%.*}" + echo "generating $file" + sed "s/Template/$class/g" "./Generator/Template.txt" > "./$class.generated.cs" +done \ No newline at end of file diff --git a/csharp/Lib/StatusApi/MpptStatus.cs b/csharp/Lib/StatusApi/MpptStatus.cs index bec31ddec..6514ad5f0 100644 --- a/csharp/Lib/StatusApi/MpptStatus.cs +++ b/csharp/Lib/StatusApi/MpptStatus.cs @@ -1,8 +1,14 @@ using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public record MpptStatus(DcPhase Dc, IReadOnlyList Strings) : IDcConnection, IPvConnection; +[OpParallel] +public partial record MpptStatus : IDcConnection, IPvConnection +{ + public required DcPhase Dc { get; init; } + public required IReadOnlyList Strings { get; init; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/MpptStatus.generated.cs b/csharp/Lib/StatusApi/MpptStatus.generated.cs new file mode 100644 index 000000000..5e2afe796 --- /dev/null +++ b/csharp/Lib/StatusApi/MpptStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = MpptStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record MpptStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/PowerMeterStatus.cs b/csharp/Lib/StatusApi/PowerMeterStatus.cs index 41038f4dc..d02a2ea72 100644 --- a/csharp/Lib/StatusApi/PowerMeterStatus.cs +++ b/csharp/Lib/StatusApi/PowerMeterStatus.cs @@ -1,6 +1,11 @@ using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record PowerMeterStatus(Ac1Phase Ac3) : DeviceStatus, IAc3Connection; \ No newline at end of file +[OpParallel] +public partial record PowerMeterStatus : DeviceStatus, IAc3Connection +{ + public required Ac3Phase Ac { get; init; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/PowerMeterStatus.generated.cs b/csharp/Lib/StatusApi/PowerMeterStatus.generated.cs new file mode 100644 index 000000000..9e6dcaf9c --- /dev/null +++ b/csharp/Lib/StatusApi/PowerMeterStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = PowerMeterStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record PowerMeterStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs index 9e1e2c8ba..efd9e7f5c 100644 --- a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs @@ -1,9 +1,15 @@ using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record SinglePhaseInverterStatus(Ac1Phase Ac, DcPhase Dc) : +[OpParallel] +public partial record SinglePhaseInverterStatus : DeviceStatus, IAc1Connection, - IDcConnection; + IDcConnection +{ + public required Ac1Phase Ac { get; init; } + public required DcPhase Dc { get; init; } +} diff --git a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.generated.cs b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.generated.cs new file mode 100644 index 000000000..047f609fc --- /dev/null +++ b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = SinglePhaseInverterStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record SinglePhaseInverterStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs index 51c113fce..3fc2db56a 100644 --- a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs @@ -1,9 +1,15 @@ using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record SinglePhasePvInverterStatus(Ac1Phase Ac, IReadOnlyList Strings) : +[OpParallel] +public partial record SinglePhasePvInverterStatus : DeviceStatus, IAc1Connection, - IPvConnection; + IPvConnection +{ + public required Ac1Phase Ac { get; init; } + public required IReadOnlyList Strings { get; init; } +} diff --git a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.generated.cs b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.generated.cs new file mode 100644 index 000000000..37340f111 --- /dev/null +++ b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = SinglePhasePvInverterStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record SinglePhasePvInverterStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/StatusApi.csproj b/csharp/Lib/StatusApi/StatusApi.csproj index 88fda982e..d14ca02c9 100644 --- a/csharp/Lib/StatusApi/StatusApi.csproj +++ b/csharp/Lib/StatusApi/StatusApi.csproj @@ -3,9 +3,13 @@ - + + + + + diff --git a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs index 8c2fc424f..306430190 100644 --- a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs +++ b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs @@ -1,10 +1,16 @@ using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record ThreePhaseInverterStatus(Ac1Phase Ac3, DcPhase Dc) : +[OpParallel] +public partial record ThreePhaseInverterStatus : DeviceStatus, IAc3Connection, - IDcConnection; + IDcConnection +{ + public required Ac3Phase Ac { get; init; } + public required DcPhase Dc { get; init; } +} \ No newline at end of file diff --git a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.generated.cs b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.generated.cs new file mode 100644 index 000000000..989941505 --- /dev/null +++ b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = ThreePhaseInverterStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record ThreePhaseInverterStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs index c09471d4b..b5a7686da 100644 --- a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs +++ b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs @@ -1,9 +1,15 @@ using InnovEnergy.Lib.StatusApi.Connections; +using InnovEnergy.Lib.StatusApi.Generator; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; -public abstract record ThreePhasePvInverterStatus(Ac1Phase Ac3, IReadOnlyList Strings) : +[OpParallel] +public partial record ThreePhasePvInverterStatus : DeviceStatus, IAc3Connection, - IPvConnection; + IPvConnection +{ + public required Ac3Phase Ac { get; init; } + public required IReadOnlyList Strings { get; init; } +} diff --git a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.generated.cs b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.generated.cs new file mode 100644 index 000000000..4e7170a21 --- /dev/null +++ b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.generated.cs @@ -0,0 +1,16 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +using System.CodeDom.Compiler; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.StatusApi; + +using T = ThreePhasePvInverterStatus; + +[GeneratedCode("generate.sh", "1")] +public partial record ThreePhasePvInverterStatus +{ + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static T operator |(T left, T right) => OpParallel(left, right); +} + \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Utils.cs b/csharp/Lib/StatusApi/Utils.cs deleted file mode 100644 index b86db8478..000000000 --- a/csharp/Lib/StatusApi/Utils.cs +++ /dev/null @@ -1,11 +0,0 @@ -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.StatusApi; - -public static class Utils -{ - public static Decimal Round3(this Decimal d) - { - return d.RoundToSignificantFigures(3); - } -} \ No newline at end of file From 9bf23f3ec822bf0246c06ef85580dbde41a3b8e8 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:14:08 +0100 Subject: [PATCH 029/114] add Percent % to Units --- csharp/Lib/Units/Percent.cs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 csharp/Lib/Units/Percent.cs diff --git a/csharp/Lib/Units/Percent.cs b/csharp/Lib/Units/Percent.cs new file mode 100644 index 000000000..02bf1a146 --- /dev/null +++ b/csharp/Lib/Units/Percent.cs @@ -0,0 +1,29 @@ +namespace InnovEnergy.Lib.Units; + +using T = Percent; + +public readonly struct Percent +{ + public static String Unit => "%"; + public static String Symbol => "%"; // ?? + + public Percent(Decimal value) + { + if (value < 0) + throw new ArgumentException(nameof(Frequency) + " cannot be negative", nameof(value)); + + Value = value; + } + + // not generated + + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + public static Decimal operator *(Decimal scalar, T t) => scalar * t.Value/100m; + public static Decimal operator *(T t, Decimal scalar) => scalar * t.Value/100m; + + // parallel + public static Percent operator |(T left, T right) => new T((left.Value + right.Value)/2m); +} \ No newline at end of file From f6f4326afa1dbb6cd4f20e08268a5a263bf3f81d Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:14:32 +0100 Subject: [PATCH 030/114] update BatteryStatus to include SOC and Temperature --- csharp/Lib/StatusApi/BatteryStatus.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/csharp/Lib/StatusApi/BatteryStatus.cs b/csharp/Lib/StatusApi/BatteryStatus.cs index 2e241e5a9..fc8961fd1 100644 --- a/csharp/Lib/StatusApi/BatteryStatus.cs +++ b/csharp/Lib/StatusApi/BatteryStatus.cs @@ -1,5 +1,6 @@ using InnovEnergy.Lib.StatusApi.Connections; using InnovEnergy.Lib.StatusApi.Generator; +using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.StatusApi; @@ -9,6 +10,8 @@ using T = BatteryStatus; [OpParallel] public partial record BatteryStatus : DeviceStatus, IDcConnection { - public required DcPhase Dc { get; init; } + public required DcPhase Dc { get; init; } + public required Percent Soc { get; init; } + public required Temperature Temperature { get; init; } } \ No newline at end of file From 08c747f2ea3fbd118800eacee4ffd31144ff5320 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:25:23 +0100 Subject: [PATCH 031/114] implement ToString for State --- csharp/Lib/Units/Percent.cs | 16 +++++----------- csharp/Lib/Units/State.cs | 10 +++++++++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/csharp/Lib/Units/Percent.cs b/csharp/Lib/Units/Percent.cs index 02bf1a146..a358c438f 100644 --- a/csharp/Lib/Units/Percent.cs +++ b/csharp/Lib/Units/Percent.cs @@ -7,23 +7,17 @@ public readonly struct Percent public static String Unit => "%"; public static String Symbol => "%"; // ?? - public Percent(Decimal value) - { - if (value < 0) - throw new ArgumentException(nameof(Frequency) + " cannot be negative", nameof(value)); - - Value = value; - } - + public Percent(Decimal value) => Value = value; + // not generated public Decimal Value { get; } public override String ToString() => Value + Unit; // scalar multiplication - public static Decimal operator *(Decimal scalar, T t) => scalar * t.Value/100m; - public static Decimal operator *(T t, Decimal scalar) => scalar * t.Value/100m; + public static Decimal operator *(Decimal scalar, T t) => scalar * t.Value / 100m; + public static Decimal operator *(T t, Decimal scalar) => scalar * t.Value / 100m; // parallel - public static Percent operator |(T left, T right) => new T((left.Value + right.Value)/2m); + public static Percent operator |(T left, T right) => new T((left.Value + right.Value) / 2m); } \ No newline at end of file diff --git a/csharp/Lib/Units/State.cs b/csharp/Lib/Units/State.cs index af96735e0..bdd76d470 100644 --- a/csharp/Lib/Units/State.cs +++ b/csharp/Lib/Units/State.cs @@ -4,7 +4,13 @@ public readonly struct State { public IReadOnlyList Values { get; } - public State(IReadOnlyList values) => Values = values; + public State(IReadOnlyList values) + { + if (values.Any(v => v.Contains(";"))) + throw new ArgumentException("State values cannot contain the character ;", nameof(values)); + + Values = values; + } public State(params String[] values) : this((IReadOnlyList)values){} public State(params State[] states) : this(states.SelectMany(s => s.Values).ToList()){} @@ -15,4 +21,6 @@ public readonly struct State public static implicit operator State(String s) => new State(s); public static State operator |(State left, State right) => new State(left, right); + + public override String ToString() => String.Join("; ", Values); } \ No newline at end of file From d91a4654cda33a0151fb6b716a8c571d764d1d12 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 08:29:36 +0100 Subject: [PATCH 032/114] add implicit op for booleans on State --- csharp/Lib/Units/State.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/csharp/Lib/Units/State.cs b/csharp/Lib/Units/State.cs index bdd76d470..ecabbd034 100644 --- a/csharp/Lib/Units/State.cs +++ b/csharp/Lib/Units/State.cs @@ -14,11 +14,10 @@ public readonly struct State public State(params String[] values) : this((IReadOnlyList)values){} public State(params State[] states) : this(states.SelectMany(s => s.Values).ToList()){} - - public State(Enum e) : this(e.ToString()){} - public static implicit operator State(Enum e) => new State(e); - public static implicit operator State(String s) => new State(s); + public static implicit operator State(String s) => new State(s); + public static implicit operator State(Enum e) => new State(e.ToString()); + public static implicit operator State(Boolean s) => new State(s.ToString()); public static State operator |(State left, State right) => new State(left, right); From d2e4f93fd14150c7076b782847eb517bb8ea215a Mon Sep 17 00:00:00 2001 From: Sina Blattmann Date: Wed, 1 Mar 2023 09:41:49 +0100 Subject: [PATCH 033/114] fix replace, so it works on windows as well --- csharp/InnovEnergy.props | 2 +- csharp/Lib/Utils/Utils.csproj | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/csharp/InnovEnergy.props b/csharp/InnovEnergy.props index 5a4943931..7315812ef 100644 --- a/csharp/InnovEnergy.props +++ b/csharp/InnovEnergy.props @@ -9,7 +9,7 @@ net6.0 true false - $(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("src/", "").Replace("/",".")) + $(Company).$(MSBuildProjectDirectory.Replace($(SolutionDir), "").Replace("src/", "").Replace("/",".").Replace("\",".")) $(Company) Team diff --git a/csharp/Lib/Utils/Utils.csproj b/csharp/Lib/Utils/Utils.csproj index 59af027d7..3ace16dcb 100644 --- a/csharp/Lib/Utils/Utils.csproj +++ b/csharp/Lib/Utils/Utils.csproj @@ -1,10 +1,6 @@ - - - - From 4cb8e9ecfa85069a6046ccc9bd469c78a7b4d686 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 10:38:46 +0100 Subject: [PATCH 034/114] add more operators to Percent --- csharp/Lib/Units/Percent.cs | 20 ++++++++++++++++++++ csharp/Lib/Units/State.cs | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/csharp/Lib/Units/Percent.cs b/csharp/Lib/Units/Percent.cs index a358c438f..577dec8a0 100644 --- a/csharp/Lib/Units/Percent.cs +++ b/csharp/Lib/Units/Percent.cs @@ -10,6 +10,7 @@ public readonly struct Percent public Percent(Decimal value) => Value = value; // not generated + // TODO: generate? public Decimal Value { get; } public override String ToString() => Value + Unit; @@ -20,4 +21,23 @@ public readonly struct Percent // parallel public static Percent operator |(T left, T right) => new T((left.Value + right.Value) / 2m); + + // compare + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); } \ No newline at end of file diff --git a/csharp/Lib/Units/State.cs b/csharp/Lib/Units/State.cs index ecabbd034..3060186de 100644 --- a/csharp/Lib/Units/State.cs +++ b/csharp/Lib/Units/State.cs @@ -13,11 +13,12 @@ public readonly struct State } public State(params String[] values) : this((IReadOnlyList)values){} - public State(params State[] states) : this(states.SelectMany(s => s.Values).ToList()){} + public State(params State[] states) : this((IReadOnlyList)states.SelectMany(s => s.Values).ToList()){} public static implicit operator State(String s) => new State(s); public static implicit operator State(Enum e) => new State(e.ToString()); public static implicit operator State(Boolean s) => new State(s.ToString()); + public static implicit operator State(List s) => new State((IReadOnlyList)s); public static State operator |(State left, State right) => new State(left, right); From f5ff1d70a5f78097faf106d316d59a4502678608 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 10:40:25 +0100 Subject: [PATCH 035/114] remove 'require' again (sigh). It only *seems* to build, but doesnt. we need net7.0 --- csharp/Lib/StatusApi/BatteryStatus.cs | 6 +++--- csharp/Lib/StatusApi/DcDcConverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/MpptStatus.cs | 4 ++-- csharp/Lib/StatusApi/PowerMeterStatus.cs | 2 +- csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs | 4 ++-- csharp/Lib/Units/Composite/Ac1Phase.cs | 4 +--- csharp/Lib/Units/Composite/Ac3Phase.cs | 10 ++++------ csharp/Lib/Units/Composite/AcPhase.cs | 10 +++++----- csharp/Lib/Units/Composite/DcPhase.cs | 6 ++---- 12 files changed, 28 insertions(+), 34 deletions(-) diff --git a/csharp/Lib/StatusApi/BatteryStatus.cs b/csharp/Lib/StatusApi/BatteryStatus.cs index fc8961fd1..0f1fedc46 100644 --- a/csharp/Lib/StatusApi/BatteryStatus.cs +++ b/csharp/Lib/StatusApi/BatteryStatus.cs @@ -10,8 +10,8 @@ using T = BatteryStatus; [OpParallel] public partial record BatteryStatus : DeviceStatus, IDcConnection { - public required DcPhase Dc { get; init; } - public required Percent Soc { get; init; } - public required Temperature Temperature { get; init; } + public DcPhase Dc { get; init; } + public Percent Soc { get; init; } + public Temperature Temperature { get; init; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/DcDcConverterStatus.cs b/csharp/Lib/StatusApi/DcDcConverterStatus.cs index a7d931065..de33033d2 100644 --- a/csharp/Lib/StatusApi/DcDcConverterStatus.cs +++ b/csharp/Lib/StatusApi/DcDcConverterStatus.cs @@ -6,8 +6,8 @@ namespace InnovEnergy.Lib.StatusApi; [OpParallel] public partial record DcDcConverterStatus : DeviceStatus { - public required DcPhase Left { get; init; } - public required DcPhase Right { get; init; } + public DcPhase Left { get; init; } + public DcPhase Right { get; init; } } diff --git a/csharp/Lib/StatusApi/MpptStatus.cs b/csharp/Lib/StatusApi/MpptStatus.cs index 6514ad5f0..99d4df09b 100644 --- a/csharp/Lib/StatusApi/MpptStatus.cs +++ b/csharp/Lib/StatusApi/MpptStatus.cs @@ -7,8 +7,8 @@ namespace InnovEnergy.Lib.StatusApi; [OpParallel] public partial record MpptStatus : IDcConnection, IPvConnection { - public required DcPhase Dc { get; init; } - public required IReadOnlyList Strings { get; init; } + public DcPhase Dc { get; init; } + public IReadOnlyList Strings { get; init; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/PowerMeterStatus.cs b/csharp/Lib/StatusApi/PowerMeterStatus.cs index d02a2ea72..26552861e 100644 --- a/csharp/Lib/StatusApi/PowerMeterStatus.cs +++ b/csharp/Lib/StatusApi/PowerMeterStatus.cs @@ -7,5 +7,5 @@ namespace InnovEnergy.Lib.StatusApi; [OpParallel] public partial record PowerMeterStatus : DeviceStatus, IAc3Connection { - public required Ac3Phase Ac { get; init; } + public Ac3Phase Ac { get; init; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs index efd9e7f5c..caaec0d94 100644 --- a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs @@ -10,6 +10,6 @@ public partial record SinglePhaseInverterStatus : IAc1Connection, IDcConnection { - public required Ac1Phase Ac { get; init; } - public required DcPhase Dc { get; init; } + public Ac1Phase Ac { get; init; } + public DcPhase Dc { get; init; } } diff --git a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs index 3fc2db56a..d6d885a78 100644 --- a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs @@ -10,6 +10,6 @@ public partial record SinglePhasePvInverterStatus : IAc1Connection, IPvConnection { - public required Ac1Phase Ac { get; init; } - public required IReadOnlyList Strings { get; init; } + public Ac1Phase Ac { get; init; } + public IReadOnlyList Strings { get; init; } } diff --git a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs index 306430190..e9fe03d3c 100644 --- a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs +++ b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs @@ -10,7 +10,7 @@ public partial record ThreePhaseInverterStatus : IAc3Connection, IDcConnection { - public required Ac3Phase Ac { get; init; } - public required DcPhase Dc { get; init; } + public Ac3Phase Ac { get; init; } + public DcPhase Dc { get; init; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs index b5a7686da..c2fb05d30 100644 --- a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs +++ b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs @@ -10,6 +10,6 @@ public partial record ThreePhasePvInverterStatus : IAc3Connection, IPvConnection { - public required Ac3Phase Ac { get; init; } - public required IReadOnlyList Strings { get; init; } + public Ac3Phase Ac { get; init; } + public IReadOnlyList Strings { get; init; } } diff --git a/csharp/Lib/Units/Composite/Ac1Phase.cs b/csharp/Lib/Units/Composite/Ac1Phase.cs index d7cfc20e7..40ddd54b0 100644 --- a/csharp/Lib/Units/Composite/Ac1Phase.cs +++ b/csharp/Lib/Units/Composite/Ac1Phase.cs @@ -1,11 +1,10 @@ - using System.Diagnostics.CodeAnalysis; namespace InnovEnergy.Lib.Units.Composite; public record Ac1Phase : AcPhase { - public required Frequency Frequency { get; init; } + public Frequency Frequency { get; init; } [SuppressMessage("ReSharper", "RedundantCast")] public static Ac1Phase operator |(Ac1Phase left, Ac1Phase right) @@ -21,7 +20,6 @@ public record Ac1Phase : AcPhase Phi = p.Phi }; } - } diff --git a/csharp/Lib/Units/Composite/Ac3Phase.cs b/csharp/Lib/Units/Composite/Ac3Phase.cs index d73f8e9e4..a80f89ba0 100644 --- a/csharp/Lib/Units/Composite/Ac3Phase.cs +++ b/csharp/Lib/Units/Composite/Ac3Phase.cs @@ -5,10 +5,10 @@ namespace InnovEnergy.Lib.Units.Composite; public record Ac3Phase { - public required AcPhase L1 { get; init; } - public required AcPhase L2 { get; init; } - public required AcPhase L3 { get; init; } - public required Frequency Frequency { get; init; } + public AcPhase L1 { get; init; } + public AcPhase L2 { get; init; } + public AcPhase L3 { get; init; } + public Frequency Frequency { get; init; } public ApparentPower ApparentPower => L1.ApparentPower + L2.ApparentPower + L3.ApparentPower; public ReactivePower ReactivePower => L1.ReactivePower + L2.ReactivePower + L3.ReactivePower; @@ -17,6 +17,4 @@ public record Ac3Phase public static Ac3Phase operator |(Ac3Phase left, Ac3Phase right) => OpParallel(left, right); private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); - - } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/AcPhase.cs b/csharp/Lib/Units/Composite/AcPhase.cs index 426091fbc..de526650d 100644 --- a/csharp/Lib/Units/Composite/AcPhase.cs +++ b/csharp/Lib/Units/Composite/AcPhase.cs @@ -6,20 +6,20 @@ namespace InnovEnergy.Lib.Units.Composite; public record AcPhase : IPhase { private readonly Voltage _Voltage; - public required Voltage Voltage + public Voltage Voltage { get => _Voltage; - init => _Voltage = value >= 0 ? value : throw new ArgumentException("RMS value cannot be negative"); + init => _Voltage = value >= 0m ? value : throw new ArgumentException("RMS value cannot be negative"); } private readonly Current _Current; - public required Current Current + public Current Current { get => _Current; - init => _Current = value >= 0 ? value : throw new ArgumentException("RMS value cannot be negative"); + init => _Current = value >= 0m ? value : throw new ArgumentException("RMS value cannot be negative"); } - public required Angle Phi { get; init; } + public Angle Phi { get; init; } public ApparentPower ApparentPower => Voltage.Value * Current.Value ; public Power ActivePower => ApparentPower.Value * PowerFactor; diff --git a/csharp/Lib/Units/Composite/DcPhase.cs b/csharp/Lib/Units/Composite/DcPhase.cs index 2d0b24b68..919589b6a 100644 --- a/csharp/Lib/Units/Composite/DcPhase.cs +++ b/csharp/Lib/Units/Composite/DcPhase.cs @@ -4,13 +4,11 @@ namespace InnovEnergy.Lib.Units.Composite; public record DcPhase : IPhase { - public required Voltage Voltage { get; init;} - public required Current Current { get; init;} + public Voltage Voltage { get; init; } + public Current Current { get; init; } public Power Power => Current * Voltage; public static DcPhase operator |(DcPhase left, DcPhase right) => OpParallel(left, right); private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); - - } \ No newline at end of file From 4bf9deffac921dac6a8dab9c357869379aa4c1d1 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 10:41:13 +0100 Subject: [PATCH 036/114] lift Battery48TL to new StatusApi --- .../Devices/Battery48TL/Battery48TLDevice.cs | 103 +------ .../Battery48TL/Battery48TLStatusRecord.cs | 71 +++-- .../Devices/Battery48TL/BatteryDataParser.cs | 167 ----------- .../Lib/Devices/Battery48TL/ModbusParser.cs | 272 ++++++++++++++++++ 4 files changed, 316 insertions(+), 297 deletions(-) delete mode 100644 csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs create mode 100644 csharp/Lib/Devices/Battery48TL/ModbusParser.cs diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs index 979eafaf7..6507ac32d 100644 --- a/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs +++ b/csharp/Lib/Devices/Battery48TL/Battery48TLDevice.cs @@ -1,7 +1,5 @@ using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; -using InnovEnergy.Lib.Protocols.Modbus.Conversions; -using InnovEnergy.Lib.StatusApi.Connections; namespace InnovEnergy.Lib.Devices.Battery48TL; @@ -33,18 +31,11 @@ public class Battery48TlDevice public Battery48TLStatus? ReadStatus() //Already try catch is implemented { - if (Modbus is null) // TODO : remove fake - { - Console.WriteLine("Battery is null"); - return null; - } - - // Console.WriteLine("Reading Battery Data"); - try { - var registers = Modbus.ReadInputRegisters(Constants.BaseAddress, Constants.NoOfRegisters); - return TryReadStatus(registers); + return Modbus + .ReadInputRegisters(Constants.BaseAddress, Constants.NoOfRegisters) + .ParseBatteryStatus(); } catch (Exception e) { @@ -53,92 +44,4 @@ public class Battery48TlDevice return null; } } - - private Battery48TLStatus? TryReadStatus(ModbusRegisters data) - { - var soc = data.ParseDecimal(register: 1054, scaleFactor: 0.1m); - var eocReached = data.ParseEocReached(); - - var warnings = new List(); - - if (data.ParseBool(1006, 1)) warnings.Add("TaM1: BMS temperature high"); - if (data.ParseBool(1006, 4)) warnings.Add("TbM1: Battery temperature high"); - if (data.ParseBool(1006, 6)) warnings.Add("VBm1: Bus voltage low"); - if (data.ParseBool(1006, 8)) warnings.Add("VBM1: Bus voltage high"); - if (data.ParseBool(1006, 10)) warnings.Add("IDM1: Discharge current high"); - if (data.ParseBool(1006, 24)) warnings.Add("vsM1: String voltage high"); - if (data.ParseBool(1006, 26)) warnings.Add("iCM1: Charge current high"); - if (data.ParseBool(1006, 28)) warnings.Add("iDM1: Discharge current high"); - if (data.ParseBool(1006, 30)) warnings.Add("MID1: String voltages unbalanced"); - if (data.ParseBool(1006, 32)) warnings.Add("BLPW: Not enough charging power on bus"); - if (data.ParseBool(1006, 35)) warnings.Add("Ah_W: String SOC low"); - if (data.ParseBool(1006, 38)) warnings.Add("MPMM: Midpoint wiring problem"); - if (data.ParseBool(1006, 39)) warnings.Add("TCMM:"); - if (data.ParseBool(1006, 40)) warnings.Add("TCdi: Temperature difference between strings high"); - if (data.ParseBool(1006, 41)) warnings.Add("WMTO:"); - if (data.ParseBool(1006, 44)) warnings.Add("bit44:"); - if (data.ParseBool(1006, 46)) warnings.Add("CELL1:"); - - var alarms = new List(); - - if (data.ParseBool(1010, 0)) alarms.Add("Tam : BMS temperature too low"); - if (data.ParseBool(1010, 2)) alarms.Add("TaM2 : BMS temperature too high"); - if (data.ParseBool(1010, 3)) alarms.Add("Tbm : Battery temperature too low"); - if (data.ParseBool(1010, 5)) alarms.Add("TbM2 : Battery temperature too high"); - if (data.ParseBool(1010, 7)) alarms.Add("VBm2 : Bus voltage too low"); - if (data.ParseBool(1010, 9)) alarms.Add("VBM2 : Bus voltage too high"); - if (data.ParseBool(1010, 11)) alarms.Add("IDM2 : Discharge current too high"); - if (data.ParseBool(1010, 12)) alarms.Add("ISOB : Electrical insulation failure"); - if (data.ParseBool(1010, 13)) alarms.Add("MSWE : Main switch failure"); - if (data.ParseBool(1010, 14)) alarms.Add("FUSE : Main fuse blown"); - if (data.ParseBool(1010, 15)) alarms.Add("HTRE : Battery failed to warm up"); - if (data.ParseBool(1010, 16)) alarms.Add("TCPE : Temperature sensor failure"); - if (data.ParseBool(1010, 17)) alarms.Add("STRE :"); - if (data.ParseBool(1010, 18)) alarms.Add("CME : Current sensor failure"); - if (data.ParseBool(1010, 19)) alarms.Add("HWFL : BMS hardware failure"); - if (data.ParseBool(1010, 20)) alarms.Add("HWEM : Hardware protection tripped"); - if (data.ParseBool(1010, 21)) alarms.Add("ThM : Heatsink temperature too high"); - if (data.ParseBool(1010, 22)) alarms.Add("vsm1 : String voltage too low"); - if (data.ParseBool(1010, 23)) alarms.Add("vsm2 : Low string voltage failure"); - if (data.ParseBool(1010, 25)) alarms.Add("vsM2 : String voltage too high"); - if (data.ParseBool(1010, 27)) alarms.Add("iCM2 : Charge current too high"); - if (data.ParseBool(1010, 29)) alarms.Add("iDM2 : Discharge current too high"); - if (data.ParseBool(1010, 31)) alarms.Add("MID2 : String voltage unbalance too high"); - if (data.ParseBool(1010, 33)) alarms.Add("CCBF : Internal charger hardware failure"); - if (data.ParseBool(1010, 34)) alarms.Add("AhFL :"); - if (data.ParseBool(1010, 36)) alarms.Add("TbCM :"); - if (data.ParseBool(1010, 37)) alarms.Add("BRNF :"); - if (data.ParseBool(1010, 42)) alarms.Add("HTFS : If Heaters Fuse Blown"); - if (data.ParseBool(1010, 43)) alarms.Add("DATA : Parameters out of range"); - if (data.ParseBool(1010, 45)) alarms.Add("CELL2:"); - - -return new Battery48TLStatus( - Dc: new DcConnection - ( - Voltage : data.ReadVoltage(), - Current : data.ReadCurrent()), - - Soc : !eocReached && soc >= 100m ? 99.9m : soc, - Temperature : data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400), - BusVoltage : data.ParseDecimal(register: 1002, scaleFactor: 0.01m), - GreenLed : data.ParseLedState(register: 1005, led: LedColor.Green), - AmberLed : data.ParseLedState(register: 1006, led: LedColor.Amber), - BlueLed : data.ParseLedState(register: 1005, led: LedColor.Blue), - RedLed : data.ParseLedState(register: 1005, led: LedColor.Red), - Warnings : warnings, - Alarms : alarms, - MainSwitchClosed : data.ParseBool(baseRegister: 1014, bit: 0), - AlarmOutActive : data.ParseBool(baseRegister: 1014, bit: 1), - InternalFanActive : data.ParseBool(baseRegister: 1014, bit: 2), - VoltMeasurementAllowed: data.ParseBool(baseRegister: 1014, bit: 3), - AuxRelay : data.ParseBool(baseRegister: 1014, bit: 4), - RemoteState : data.ParseBool(baseRegister: 1014, bit: 5), - HeaterOn : data.ParseBool(baseRegister: 1014, bit: 6), - EocReached : eocReached, - BatteryCold : data.ParseBatteryCold(), - MaxChargingPower : data.CalcMaxChargePower(), - MaxDischargingPower : data.CalcMaxDischargePower() - ); - } } \ No newline at end of file diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs index 0871f0645..79bc1c7df 100644 --- a/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs +++ b/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs @@ -1,39 +1,50 @@ using System.Diagnostics.CodeAnalysis; -using InnovEnergy.Lib.Protocols.Modbus.Conversions; -using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Devices; +using InnovEnergy.Lib.StatusApi; +using InnovEnergy.Lib.Units; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Devices.Battery48TL; +using T = Battery48TLStatus; + [SuppressMessage("ReSharper", "InconsistentNaming")] -public record Battery48TLStatus -( - DcConnection Dc, - Decimal Soc, - Decimal Temperature, - //Decimal Current, - //Decimal Voltage, - Decimal BusVoltage, - LedState GreenLed, - LedState AmberLed, - LedState BlueLed, - LedState RedLed, - IReadOnlyList Warnings, - IReadOnlyList Alarms, - Boolean MainSwitchClosed, - Boolean AlarmOutActive, - Boolean InternalFanActive, - Boolean VoltMeasurementAllowed, - Boolean AuxRelay, - Boolean RemoteState, - Boolean HeaterOn, - Boolean EocReached, - Boolean BatteryCold, - Decimal MaxChargingPower, - Decimal MaxDischargingPower -) -: Battery(Dc, Soc, Temperature) +public record Battery48TLStatus : BatteryStatus { + public required Voltage CellsVoltage { get; init; } + + public required Power MaxChargingPower { get; init; } + public required Power MaxDischargingPower { get; init; } + + public required State GreenLed { get; init; } + public required State AmberLed { get; init; } + public required State BlueLed { get; init; } + public required State RedLed { get; init; } + + public required State Warnings { get; init; } + public required State Alarms { get; init; } + + public required State MainSwitchState { get; init; } // connected to bus | disconnected from bus + public required State HeaterState { get; init; } // heating | not heating + public required State EocState { get; init; } // EOC reached | EOC not reached + public required State TemperatureState { get; init; } // cold | operating temperature | overheated + + + public static T operator |(T left, T right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + + + + // TODO: strings + // TODO + // public State LimitedBy { get; init; } + + // TODO + // public Boolean AlarmOutActive { get; init; } + // public Boolean InternalFanActive { get; init; } + // public Boolean VoltMeasurementAllowed { get; init; } + // public Boolean AuxRelay { get; init; } + // public Boolean RemoteState { get; init; } + } diff --git a/csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs b/csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs deleted file mode 100644 index 916c8989c..000000000 --- a/csharp/Lib/Devices/Battery48TL/BatteryDataParser.cs +++ /dev/null @@ -1,167 +0,0 @@ -using InnovEnergy.Lib.Protocols.Modbus.Conversions; -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.Devices.Battery48TL; - -public static class BatteryDataParser -{ - public static Decimal ParseDecimal(this ModbusRegisters data, Int32 register, Decimal scaleFactor = 1.0m, Double offset = 0.0) - { - var value = data[register].ConvertTo(); // widen to 32bit signed - - if (value >= 0x8000) - value -= 0x10000; // Fiamm stores their integers signed AND with sign-offset @#%^&! - - return (Decimal)(value + offset) * scaleFactor; - } - - internal static Decimal ReadCurrent(this ModbusRegisters data) - { - return ParseDecimal(data, register: 1001, scaleFactor: 0.01m, offset: -10000); - } - - internal static Decimal ReadVoltage(this ModbusRegisters data) - { - return ParseDecimal(data, register: 1000, scaleFactor: 0.01m); - } - - internal static Boolean ParseBool(this ModbusRegisters data, Int32 baseRegister, Int16 bit) - { - var x = bit / 16; - var y = bit % 16; - - var value = (UInt32)data[baseRegister + x]; - - return (value & (1 << y)) > 0; - } - - internal static LedState ParseLedState(this ModbusRegisters data, Int32 register, LedColor led) - { - var lo = ParseBool(data, register, (led.ConvertTo() * 2).ConvertTo()); - var hi = ParseBool(data, register, (led.ConvertTo() * 2 + 1).ConvertTo()); - - if (hi) - { - if (lo) - { - return LedState.BlinkingFast; - } - else - { - return LedState.BlinkingSlow; - } - } - else - { - if (lo) - { - return LedState.On; - } - else - { - return LedState.Off; - } - } - - } - - internal static String ParseRegisters(this ModbusRegisters data, Int32 register, Int16 count) - { - var container = ""; - - var start = register; - var end = register + count; - - for (var i = start; i < end; i++) - { - var binary = Convert.ToString(data[register], 2); - container += binary.PadLeft(16, '0'); - } - return container; - } - - internal static Boolean ParseEocReached(this ModbusRegisters data) - { - return ParseLedState(data, 1005, LedColor.Green) == LedState.On && - ParseLedState(data, 1005, LedColor.Amber) == LedState.Off && - ParseLedState(data, 1005, LedColor.Blue) == LedState.Off; - } - - internal static Boolean ParseBatteryCold(this ModbusRegisters data) - { - return ParseLedState(data, 1005, LedColor.Green) >= LedState.BlinkingSlow && - ParseLedState(data, 1005, LedColor.Blue) >= LedState.BlinkingSlow; - } - - private static Decimal CalcPowerLimitImposedByVoltageLimit(Decimal v,Decimal i,Decimal vLimit,Decimal rInt) - { - var dv = vLimit - v; - var di = dv / rInt; - var pLimit = vLimit * (i + di); - - return pLimit; - } - - private static Decimal CalcPowerLimitImposedByCurrentLimit(Decimal v, Decimal i, Decimal iLimit, Decimal rInt) - { - var di = iLimit - i; - var dv = di * rInt; - var pLimit = iLimit * (v + dv); - - return pLimit; - } - - - private static Decimal CalcPowerLimitImposedByTempLimit(Decimal t, Decimal maxAllowedTemp, Decimal power , Decimal setpoint) - { - // const Int32 holdZone = 300; - // const Int32 maxAllowedTemp = 315; - - var kp = 0.05m; - var error = setpoint - power; - var controlOutput = (kp * error) *(1 - Math.Abs((t-307.5m)/7.5m)); - - return controlOutput; - - // var a = holdZone - maxAllowedTemp; - // var b = -a * maxAllowedTemp; - } - - internal static Decimal CalcMaxChargePower(this ModbusRegisters data) - { - var v = ReadVoltage(data); - var i = ReadCurrent(data); - - var pLimits = new[] - { - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMin), - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMax), - CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMin), - CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMax) - }; - - var pLimit = pLimits.Min(); - - return Math.Max(pLimit, 0); - } - - internal static Decimal CalcMaxDischargePower(this ModbusRegisters data) - { - var v = ReadVoltage(data); - var i = ReadCurrent(data); - var t = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400); - - var pLimits = new[] - { - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMin), - CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMax), - CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMin), - CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMax), - // CalcPowerLimitImposedByTempLimit(t,315,300) - }; - - var pLimit = pLimits.Max(); - - return Math.Min(pLimit, 0); - } -} \ No newline at end of file diff --git a/csharp/Lib/Devices/Battery48TL/ModbusParser.cs b/csharp/Lib/Devices/Battery48TL/ModbusParser.cs new file mode 100644 index 000000000..dbc15a3e4 --- /dev/null +++ b/csharp/Lib/Devices/Battery48TL/ModbusParser.cs @@ -0,0 +1,272 @@ +using System.Diagnostics.CodeAnalysis; +using InnovEnergy.Lib.Protocols.Modbus.Conversions; +using InnovEnergy.Lib.Units; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.Devices.Battery48TL; + +public static class ModbusParser +{ + internal static Battery48TLStatus ParseBatteryStatus(this ModbusRegisters data) + { + return new Battery48TLStatus + { + Dc = data.ParseDcBus(), + Alarms = data.ParseAlarms().ToList(), + Warnings = data.ParseWarnings().ToList(), + Soc = data.ParseSoc(), + Temperature = data.ParseTemperature(), + GreenLed = data.ParseGreenLed(), + AmberLed = data.ParseAmberLed(), + BlueLed = data.ParseBlueLed(), + RedLed = data.ParseRedLed(), + MainSwitchState = data.ParseMainSwitchState(), + HeaterState = data.ParseHeaterState(), + EocState = data.ParseEocState(), + TemperatureState = data.ParseTemperatureState(), + MaxChargingPower = data.CalcMaxChargePower(), + MaxDischargingPower = data.CalcMaxDischargePower(), + CellsVoltage = data.ParseCellsVoltage(), + }; + } + + + public static Decimal ParseDecimal(this ModbusRegisters data, Int32 register, Decimal scaleFactor = 1.0m, Double offset = 0.0) + { + var value = data[register].ConvertTo(); // widen to 32bit signed + + if (value >= 0x8000) + value -= 0x10000; // Fiamm stores their integers signed AND with sign-offset @#%^&! + + return (Decimal)(value + offset) * scaleFactor; + } + + internal static Decimal ParseCurrent(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1001, scaleFactor: 0.01m, offset: -10000); + } + + internal static Decimal ParseCellsVoltage(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1000, scaleFactor: 0.01m); + } + + internal static Decimal ParseBusVoltage(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1002, scaleFactor: 0.01m); + } + + internal static Boolean ParseBool(this ModbusRegisters data, Int32 baseRegister, Int16 bit) + { + var x = bit / 16; + var y = bit % 16; + + var value = (UInt32)data[baseRegister + x]; + + return (value & (1 << y)) > 0; + } + + internal static LedState ParseLedState(this ModbusRegisters data, Int32 register, LedColor led) + { + var lo = data.ParseBool(register, (led.ConvertTo() * 2 ).ConvertTo()); + var hi = data.ParseBool(register, (led.ConvertTo() * 2 + 1).ConvertTo()); + + return (hi, lo) switch + { + (false, false) => LedState.Off, + (false, true) => LedState.On, + (true, false) => LedState.BlinkingSlow, + (true, true) => LedState.BlinkingFast, + }; + } + + + private static Boolean ParseEocReached(this ModbusRegisters data) + { + return ParseLedState(data, 1005, LedColor.Green) == LedState.On && + ParseLedState(data, 1005, LedColor.Amber) == LedState.Off && + ParseLedState(data, 1005, LedColor.Blue) == LedState.Off; + } + + internal static State ParseTemperatureState(this ModbusRegisters data) + { + return data.ParseBatteryCold() ? "cold" : "operating temperature"; // TODO: overheated, + } + + internal static Decimal ParseTemperature(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400); + } + + internal static Decimal ParseSoc(this ModbusRegisters data) + { + return data.ParseDecimal(register: 1054, scaleFactor: 0.1m); + } + + internal static State ParseEocState(this ModbusRegisters data) + { + return data.ParseEocReached() ? "EOC reached" : "EOC not reached"; + } + + internal static State ParseHeaterState(this ModbusRegisters data) + { + return data.ParseBool(baseRegister: 1014, bit: 6) ? "heating" : "not heating"; + } + + internal static State ParseMainSwitchState(this ModbusRegisters data) + { + return data.ParseBool(baseRegister: 1014, bit: 0) ? "connected to bus" : "disconnected from bus"; + } + + internal static Boolean ParseBatteryCold(this ModbusRegisters data) + { + return ParseLedState(data, 1005, LedColor.Green) >= LedState.BlinkingSlow && + ParseLedState(data, 1005, LedColor.Blue) >= LedState.BlinkingSlow; + } + + private static Decimal CalcPowerLimitImposedByVoltageLimit(Decimal v,Decimal i,Decimal vLimit,Decimal rInt) + { + var dv = vLimit - v; + var di = dv / rInt; + var pLimit = vLimit * (i + di); + + return pLimit; + } + + private static Decimal CalcPowerLimitImposedByCurrentLimit(Decimal v, Decimal i, Decimal iLimit, Decimal rInt) + { + var di = iLimit - i; + var dv = di * rInt; + var pLimit = iLimit * (v + dv); + + return pLimit; + } + + + private static Decimal CalcPowerLimitImposedByTempLimit(Decimal t, Decimal maxAllowedTemp, Decimal power , Decimal setpoint) + { + // const Int32 holdZone = 300; + // const Int32 maxAllowedTemp = 315; + + var kp = 0.05m; + var error = setpoint - power; + var controlOutput = (kp * error) *(1 - Math.Abs((t-307.5m)/7.5m)); + + return controlOutput; + + // var a = holdZone - maxAllowedTemp; + // var b = -a * maxAllowedTemp; + } + + internal static Decimal CalcMaxChargePower(this ModbusRegisters data) + { + var v = ParseCellsVoltage(data); + var i = ParseCurrent(data); + + var pLimits = new[] + { + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMin), + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMax, Constants.RIntMax), + CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMin), + CalcPowerLimitImposedByCurrentLimit(v, i, Constants.IMax, Constants.RIntMax) + }; + + var pLimit = pLimits.Min(); + + return Math.Max(pLimit, 0); + } + + internal static DcPhase ParseDcBus(this ModbusRegisters data) + { + return new() + { + Current = data.ParseCurrent(), + Voltage = data.ParseBusVoltage(), + }; + } + + internal static Decimal CalcMaxDischargePower(this ModbusRegisters data) + { + var v = ParseCellsVoltage(data); + var i = ParseCurrent(data); + var t = data.ParseDecimal(register: 1004, scaleFactor: 0.1m, offset: -400); + + var pLimits = new[] + { + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMin), + CalcPowerLimitImposedByVoltageLimit(v, i, Constants.VMin, Constants.RIntMax), + CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMin), + CalcPowerLimitImposedByCurrentLimit(v, i, -Constants.IMax, Constants.RIntMax), + // CalcPowerLimitImposedByTempLimit(t,315,300) + }; + + var pLimit = pLimits.Max(); + + return Math.Min(pLimit, 0); + } + + + internal static LedState ParseGreenLed(this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Green); + internal static LedState ParseAmberLed(this ModbusRegisters data) => data.ParseLedState(register: 1006, led: LedColor.Amber); + internal static LedState ParseBlueLed (this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Blue); + internal static LedState ParseRedLed (this ModbusRegisters data) => data.ParseLedState(register: 1005, led: LedColor.Red); + + + [SuppressMessage("ReSharper", "StringLiteralTypo")] + internal static IEnumerable ParseAlarms(this ModbusRegisters data) + { + if (data.ParseBool(1010, 0)) yield return "Tam : BMS temperature too low"; + if (data.ParseBool(1010, 2)) yield return "TaM2 : BMS temperature too high"; + if (data.ParseBool(1010, 3)) yield return "Tbm : Battery temperature too low"; + if (data.ParseBool(1010, 5)) yield return "TbM2 : Battery temperature too high"; + if (data.ParseBool(1010, 7)) yield return "VBm2 : Bus voltage too low"; + if (data.ParseBool(1010, 9)) yield return "VBM2 : Bus voltage too high"; + if (data.ParseBool(1010, 11)) yield return "IDM2 : Discharge current too high"; + if (data.ParseBool(1010, 12)) yield return "ISOB : Electrical insulation failure"; + if (data.ParseBool(1010, 13)) yield return "MSWE : Main switch failure"; + if (data.ParseBool(1010, 14)) yield return "FUSE : Main fuse blown"; + if (data.ParseBool(1010, 15)) yield return "HTRE : Battery failed to warm up"; + if (data.ParseBool(1010, 16)) yield return "TCPE : Temperature sensor failure"; + if (data.ParseBool(1010, 17)) yield return "STRE :"; + if (data.ParseBool(1010, 18)) yield return "CME : Current sensor failure"; + if (data.ParseBool(1010, 19)) yield return "HWFL : BMS hardware failure"; + if (data.ParseBool(1010, 20)) yield return "HWEM : Hardware protection tripped"; + if (data.ParseBool(1010, 21)) yield return "ThM : Heatsink temperature too high"; + if (data.ParseBool(1010, 22)) yield return "vsm1 : String voltage too low"; + if (data.ParseBool(1010, 23)) yield return "vsm2 : Low string voltage failure"; + if (data.ParseBool(1010, 25)) yield return "vsM2 : String voltage too high"; + if (data.ParseBool(1010, 27)) yield return "iCM2 : Charge current too high"; + if (data.ParseBool(1010, 29)) yield return "iDM2 : Discharge current too high"; + if (data.ParseBool(1010, 31)) yield return "MID2 : String voltage unbalance too high"; + if (data.ParseBool(1010, 33)) yield return "CCBF : Internal charger hardware failure"; + if (data.ParseBool(1010, 34)) yield return "AhFL :"; + if (data.ParseBool(1010, 36)) yield return "TbCM :"; + if (data.ParseBool(1010, 37)) yield return "BRNF :"; + if (data.ParseBool(1010, 42)) yield return "HTFS : If Heaters Fuse Blown"; + if (data.ParseBool(1010, 43)) yield return "DATA : Parameters out of range"; + if (data.ParseBool(1010, 45)) yield return "CELL2:"; + } + + [SuppressMessage("ReSharper", "StringLiteralTypo")] + internal static IEnumerable ParseWarnings(this ModbusRegisters data) + { + if (data.ParseBool(1006, 1)) yield return "TaM1: BMS temperature high"; + if (data.ParseBool(1006, 4)) yield return "TbM1: Battery temperature high"; + if (data.ParseBool(1006, 6)) yield return "VBm1: Bus voltage low"; + if (data.ParseBool(1006, 8)) yield return "VBM1: Bus voltage high"; + if (data.ParseBool(1006, 10)) yield return "IDM1: Discharge current high"; + if (data.ParseBool(1006, 24)) yield return "vsM1: String voltage high"; + if (data.ParseBool(1006, 26)) yield return "iCM1: Charge current high"; + if (data.ParseBool(1006, 28)) yield return "iDM1: Discharge current high"; + if (data.ParseBool(1006, 30)) yield return "MID1: String voltages unbalanced"; + if (data.ParseBool(1006, 32)) yield return "BLPW: Not enough charging power on bus"; + if (data.ParseBool(1006, 35)) yield return "Ah_W: String SOC low"; + if (data.ParseBool(1006, 38)) yield return "MPMM: Midpoint wiring problem"; + if (data.ParseBool(1006, 39)) yield return "TCMM:"; + if (data.ParseBool(1006, 40)) yield return "TCdi: Temperature difference between strings high"; + if (data.ParseBool(1006, 41)) yield return "WMTO:"; + if (data.ParseBool(1006, 44)) yield return "bit44:"; + if (data.ParseBool(1006, 46)) yield return "CELL1:"; + } +} \ No newline at end of file From b983614cfc4ebb50dbd3a219697ba49955205e28 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 10:52:21 +0100 Subject: [PATCH 037/114] Phase => Bus --- .../Lib/Units/Composite/{Ac1Phase.cs => Ac1Bus.cs} | 6 +++--- .../Lib/Units/Composite/{Ac3Phase.cs => Ac3Bus.cs} | 6 +++--- csharp/Lib/Units/Composite/AcPhase.cs | 2 +- csharp/Lib/Units/Composite/DcBus.cs | 14 ++++++++++++++ csharp/Lib/Units/Composite/DcPhase.cs | 14 -------------- csharp/Lib/Units/Composite/{IPhase.cs => IBus.cs} | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) rename csharp/Lib/Units/Composite/{Ac1Phase.cs => Ac1Bus.cs} (77%) rename csharp/Lib/Units/Composite/{Ac3Phase.cs => Ac3Bus.cs} (74%) create mode 100644 csharp/Lib/Units/Composite/DcBus.cs delete mode 100644 csharp/Lib/Units/Composite/DcPhase.cs rename csharp/Lib/Units/Composite/{IPhase.cs => IBus.cs} (89%) diff --git a/csharp/Lib/Units/Composite/Ac1Phase.cs b/csharp/Lib/Units/Composite/Ac1Bus.cs similarity index 77% rename from csharp/Lib/Units/Composite/Ac1Phase.cs rename to csharp/Lib/Units/Composite/Ac1Bus.cs index 40ddd54b0..f2c769f24 100644 --- a/csharp/Lib/Units/Composite/Ac1Phase.cs +++ b/csharp/Lib/Units/Composite/Ac1Bus.cs @@ -2,17 +2,17 @@ using System.Diagnostics.CodeAnalysis; namespace InnovEnergy.Lib.Units.Composite; -public record Ac1Phase : AcPhase +public record Ac1Bus : AcPhase { public Frequency Frequency { get; init; } [SuppressMessage("ReSharper", "RedundantCast")] - public static Ac1Phase operator |(Ac1Phase left, Ac1Phase right) + public static Ac1Bus operator |(Ac1Bus left, Ac1Bus right) { var f = left.Frequency | right.Frequency; var p = (AcPhase)left | (AcPhase)right; - return new Ac1Phase + return new Ac1Bus { Frequency = f, Current = p.Current, diff --git a/csharp/Lib/Units/Composite/Ac3Phase.cs b/csharp/Lib/Units/Composite/Ac3Bus.cs similarity index 74% rename from csharp/Lib/Units/Composite/Ac3Phase.cs rename to csharp/Lib/Units/Composite/Ac3Bus.cs index a80f89ba0..e35c73cfc 100644 --- a/csharp/Lib/Units/Composite/Ac3Phase.cs +++ b/csharp/Lib/Units/Composite/Ac3Bus.cs @@ -3,7 +3,7 @@ using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Units.Composite; -public record Ac3Phase +public record Ac3Bus { public AcPhase L1 { get; init; } public AcPhase L2 { get; init; } @@ -15,6 +15,6 @@ public record Ac3Phase public Power ActivePower => L1.ActivePower + L2.ActivePower + L3.ActivePower; public Angle Phi => ATan2(ReactivePower, ActivePower); - public static Ac3Phase operator |(Ac3Phase left, Ac3Phase right) => OpParallel(left, right); - private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); + public static Ac3Bus operator |(Ac3Bus left, Ac3Bus right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); } \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/AcPhase.cs b/csharp/Lib/Units/Composite/AcPhase.cs index de526650d..faa20f23d 100644 --- a/csharp/Lib/Units/Composite/AcPhase.cs +++ b/csharp/Lib/Units/Composite/AcPhase.cs @@ -3,7 +3,7 @@ using static DecimalMath.DecimalEx; namespace InnovEnergy.Lib.Units.Composite; -public record AcPhase : IPhase +public record AcPhase : IBus { private readonly Voltage _Voltage; public Voltage Voltage diff --git a/csharp/Lib/Units/Composite/DcBus.cs b/csharp/Lib/Units/Composite/DcBus.cs new file mode 100644 index 000000000..9bab0143a --- /dev/null +++ b/csharp/Lib/Units/Composite/DcBus.cs @@ -0,0 +1,14 @@ +using InnovEnergy.Lib.Utils; + +namespace InnovEnergy.Lib.Units.Composite; + +public record DcBus : IBus +{ + public Voltage Voltage { get; init; } + public Current Current { get; init; } + + public Power Power => Current * Voltage; + + public static DcBus operator |(DcBus left, DcBus right) => OpParallel(left, right); + private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); +} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/DcPhase.cs b/csharp/Lib/Units/Composite/DcPhase.cs deleted file mode 100644 index 919589b6a..000000000 --- a/csharp/Lib/Units/Composite/DcPhase.cs +++ /dev/null @@ -1,14 +0,0 @@ -using InnovEnergy.Lib.Utils; - -namespace InnovEnergy.Lib.Units.Composite; - -public record DcPhase : IPhase -{ - public Voltage Voltage { get; init; } - public Current Current { get; init; } - - public Power Power => Current * Voltage; - - public static DcPhase operator |(DcPhase left, DcPhase right) => OpParallel(left, right); - private static readonly Func OpParallel = "|".CreateBinaryOpForProps(); -} \ No newline at end of file diff --git a/csharp/Lib/Units/Composite/IPhase.cs b/csharp/Lib/Units/Composite/IBus.cs similarity index 89% rename from csharp/Lib/Units/Composite/IPhase.cs rename to csharp/Lib/Units/Composite/IBus.cs index b0ccfee66..8b9694972 100644 --- a/csharp/Lib/Units/Composite/IPhase.cs +++ b/csharp/Lib/Units/Composite/IBus.cs @@ -4,7 +4,7 @@ namespace InnovEnergy.Lib.Units.Composite; [SuppressMessage("ReSharper", "MemberCanBeProtected.Global")] -public interface IPhase +public interface IBus { public Voltage Voltage { get; } public Current Current { get; } From fac1a090bfb06edfc454a3fac05cbfb9d2adf7a6 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 10:52:54 +0100 Subject: [PATCH 038/114] Phase => Bus --- csharp/Lib/StatusApi/BatteryStatus.cs | 2 +- csharp/Lib/StatusApi/Connections/IAc1Connection.cs | 2 +- csharp/Lib/StatusApi/Connections/IAc3Connection.cs | 2 +- csharp/Lib/StatusApi/Connections/IDcConnection.cs | 2 +- csharp/Lib/StatusApi/Connections/IPvConnection.cs | 2 +- csharp/Lib/StatusApi/DcDcConverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/MpptStatus.cs | 4 ++-- csharp/Lib/StatusApi/PowerMeterStatus.cs | 2 +- csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs | 4 ++-- csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs | 4 ++-- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/csharp/Lib/StatusApi/BatteryStatus.cs b/csharp/Lib/StatusApi/BatteryStatus.cs index 0f1fedc46..6c656b1c9 100644 --- a/csharp/Lib/StatusApi/BatteryStatus.cs +++ b/csharp/Lib/StatusApi/BatteryStatus.cs @@ -10,7 +10,7 @@ using T = BatteryStatus; [OpParallel] public partial record BatteryStatus : DeviceStatus, IDcConnection { - public DcPhase Dc { get; init; } + public DcBus Dc { get; init; } public Percent Soc { get; init; } public Temperature Temperature { get; init; } } diff --git a/csharp/Lib/StatusApi/Connections/IAc1Connection.cs b/csharp/Lib/StatusApi/Connections/IAc1Connection.cs index d90b57938..54060cb20 100644 --- a/csharp/Lib/StatusApi/Connections/IAc1Connection.cs +++ b/csharp/Lib/StatusApi/Connections/IAc1Connection.cs @@ -4,5 +4,5 @@ namespace InnovEnergy.Lib.StatusApi.Connections; public interface IAc1Connection { - Ac1Phase Ac { get; } + Ac1Bus Ac { get; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IAc3Connection.cs b/csharp/Lib/StatusApi/Connections/IAc3Connection.cs index b95939124..a1c0ca1b5 100644 --- a/csharp/Lib/StatusApi/Connections/IAc3Connection.cs +++ b/csharp/Lib/StatusApi/Connections/IAc3Connection.cs @@ -4,5 +4,5 @@ namespace InnovEnergy.Lib.StatusApi.Connections; public interface IAc3Connection { - Ac3Phase Ac { get; } + Ac3Bus Ac { get; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IDcConnection.cs b/csharp/Lib/StatusApi/Connections/IDcConnection.cs index 6074a6750..04d83289f 100644 --- a/csharp/Lib/StatusApi/Connections/IDcConnection.cs +++ b/csharp/Lib/StatusApi/Connections/IDcConnection.cs @@ -5,5 +5,5 @@ namespace InnovEnergy.Lib.StatusApi.Connections; public interface IDcConnection { - DcPhase Dc { get; } + DcBus Dc { get; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/Connections/IPvConnection.cs b/csharp/Lib/StatusApi/Connections/IPvConnection.cs index a117f2d17..6dfddccea 100644 --- a/csharp/Lib/StatusApi/Connections/IPvConnection.cs +++ b/csharp/Lib/StatusApi/Connections/IPvConnection.cs @@ -4,5 +4,5 @@ namespace InnovEnergy.Lib.StatusApi.Connections; public interface IPvConnection { - IReadOnlyList Strings { get; } + IReadOnlyList Strings { get; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/DcDcConverterStatus.cs b/csharp/Lib/StatusApi/DcDcConverterStatus.cs index de33033d2..21941d5e6 100644 --- a/csharp/Lib/StatusApi/DcDcConverterStatus.cs +++ b/csharp/Lib/StatusApi/DcDcConverterStatus.cs @@ -6,8 +6,8 @@ namespace InnovEnergy.Lib.StatusApi; [OpParallel] public partial record DcDcConverterStatus : DeviceStatus { - public DcPhase Left { get; init; } - public DcPhase Right { get; init; } + public DcBus Left { get; init; } + public DcBus Right { get; init; } } diff --git a/csharp/Lib/StatusApi/MpptStatus.cs b/csharp/Lib/StatusApi/MpptStatus.cs index 99d4df09b..53acdf439 100644 --- a/csharp/Lib/StatusApi/MpptStatus.cs +++ b/csharp/Lib/StatusApi/MpptStatus.cs @@ -7,8 +7,8 @@ namespace InnovEnergy.Lib.StatusApi; [OpParallel] public partial record MpptStatus : IDcConnection, IPvConnection { - public DcPhase Dc { get; init; } - public IReadOnlyList Strings { get; init; } + public DcBus Dc { get; init; } + public IReadOnlyList Strings { get; init; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/PowerMeterStatus.cs b/csharp/Lib/StatusApi/PowerMeterStatus.cs index 26552861e..8140afef3 100644 --- a/csharp/Lib/StatusApi/PowerMeterStatus.cs +++ b/csharp/Lib/StatusApi/PowerMeterStatus.cs @@ -7,5 +7,5 @@ namespace InnovEnergy.Lib.StatusApi; [OpParallel] public partial record PowerMeterStatus : DeviceStatus, IAc3Connection { - public Ac3Phase Ac { get; init; } + public Ac3Bus Ac { get; init; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs index caaec0d94..6688d8886 100644 --- a/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhaseInverterStatus.cs @@ -10,6 +10,6 @@ public partial record SinglePhaseInverterStatus : IAc1Connection, IDcConnection { - public Ac1Phase Ac { get; init; } - public DcPhase Dc { get; init; } + public Ac1Bus Ac { get; init; } + public DcBus Dc { get; init; } } diff --git a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs index d6d885a78..269254b6e 100644 --- a/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs +++ b/csharp/Lib/StatusApi/SinglePhasePvInverterStatus.cs @@ -10,6 +10,6 @@ public partial record SinglePhasePvInverterStatus : IAc1Connection, IPvConnection { - public Ac1Phase Ac { get; init; } - public IReadOnlyList Strings { get; init; } + public Ac1Bus Ac { get; init; } + public IReadOnlyList Strings { get; init; } } diff --git a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs index e9fe03d3c..c525a6a67 100644 --- a/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs +++ b/csharp/Lib/StatusApi/ThreePhaseInverterStatus.cs @@ -10,7 +10,7 @@ public partial record ThreePhaseInverterStatus : IAc3Connection, IDcConnection { - public Ac3Phase Ac { get; init; } - public DcPhase Dc { get; init; } + public Ac3Bus Ac { get; init; } + public DcBus Dc { get; init; } } \ No newline at end of file diff --git a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs index c2fb05d30..8c122ffb3 100644 --- a/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs +++ b/csharp/Lib/StatusApi/ThreePhasePvInverterStatus.cs @@ -10,6 +10,6 @@ public partial record ThreePhasePvInverterStatus : IAc3Connection, IPvConnection { - public Ac3Phase Ac { get; init; } - public IReadOnlyList Strings { get; init; } + public Ac3Bus Ac { get; init; } + public IReadOnlyList Strings { get; init; } } From afe83e943ffd7996ed90adf084be582ae46bbd23 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 1 Mar 2023 10:53:34 +0100 Subject: [PATCH 039/114] Phase => Bus --- csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs | 4 +- .../Lib/Devices/Battery48TL/ModbusParser.cs | 2 +- csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs | 4 +- csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs | 7 +-- .../Trumpf/TruConvertAc/TruConvertAcDevice.cs | 5 +-- .../Trumpf/TruConvertAc/TruConvertAcStatus.cs | 4 +- .../Trumpf/TruConvertDc/TruConvertDcStatus.cs | 43 +++++++++++-------- 7 files changed, 37 insertions(+), 32 deletions(-) diff --git a/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs b/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs index 371395e46..8ee809b72 100644 --- a/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs +++ b/csharp/Lib/Devices/AMPT/AmptDeviceStatus.cs @@ -1,5 +1,5 @@ +using InnovEnergy.Lib.StatusApi; using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Devices; namespace InnovEnergy.Lib.Devices.AMPT; @@ -11,5 +11,5 @@ public record AmptDeviceStatus UInt32 Timestamp, // The UTC timestamp of the measurements Decimal ProductionToday, // converted to kW in AmptCU class IReadOnlyList Strings -): Mppt(Dc, Strings) +): MpptStatus(Dc, Strings) {} \ No newline at end of file diff --git a/csharp/Lib/Devices/Battery48TL/ModbusParser.cs b/csharp/Lib/Devices/Battery48TL/ModbusParser.cs index dbc15a3e4..d16c3dc5d 100644 --- a/csharp/Lib/Devices/Battery48TL/ModbusParser.cs +++ b/csharp/Lib/Devices/Battery48TL/ModbusParser.cs @@ -177,7 +177,7 @@ public static class ModbusParser return Math.Max(pLimit, 0); } - internal static DcPhase ParseDcBus(this ModbusRegisters data) + internal static DcBus ParseDcBus(this ModbusRegisters data) { return new() { diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs index c219755b3..e4a766d30 100644 --- a/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs +++ b/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs @@ -1,7 +1,7 @@ using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Phases; +using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Utils; using static DecimalMath.DecimalEx; @@ -77,7 +77,7 @@ public class EmuMeterDevice return new EmuMeterStatus ( - Ac: new ThreePhaseAcConnection + Ac: new Ac3Bus ( new AcPhase( voltageL1N, diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs index 713a4b2de..3e629c15a 100644 --- a/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs +++ b/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs @@ -1,11 +1,12 @@ +using InnovEnergy.Lib.StatusApi; using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Devices; +using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Devices.EmuMeter; public record EmuMeterStatus ( - ThreePhaseAcConnection Ac, + Ac3Bus Ac, Decimal ActivePowerL123, Decimal ReactivePowerL123, Decimal ApparentPowerL123, @@ -21,6 +22,6 @@ public record EmuMeterStatus Decimal EnergyExportL1, Decimal EnergyExportL2, Decimal EnergyExportL3 -):GridMeter(Ac) +):PowerMeterStatus(Ac) {} diff --git a/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs index 6308553aa..66cc153a7 100644 --- a/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs +++ b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcDevice.cs @@ -2,8 +2,7 @@ using System.Diagnostics.CodeAnalysis; using InnovEnergy.Lib.Devices.Trumpf.TruConvert; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; -using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Phases; +using InnovEnergy.Lib.Units.Composite; using InnovEnergy.Lib.Utils; using static DecimalMath.DecimalEx; using static InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.AcControlRegisters; @@ -216,7 +215,7 @@ public class TruConvertAcDevice return new TruConvertAcStatus ( - Ac: new ThreePhaseAcConnection + Ac: new Ac3Bus ( new AcPhase(gridVoltageL1,phaseCurrentL1, ACos(powerAcL1/apparentPowerAcL1)), new AcPhase(gridVoltageL2,phaseCurrentL2, ACos(powerAcL2/apparentPowerAcL2)), diff --git a/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs index 8f2047ebb..4747e0579 100644 --- a/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs +++ b/csharp/Lib/Devices/Trumpf/TruConvertAc/TruConvertAcStatus.cs @@ -1,6 +1,6 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvert; using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Devices; +using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; @@ -9,7 +9,7 @@ using WarningMessages = IReadOnlyList; public record TruConvertAcStatus ( - ThreePhaseAcConnection Ac, + Ac3Bus Ac, DcConnection Dc, String SerialNumber, MainState MainState, diff --git a/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs b/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs index 88551dee1..bf78b928b 100644 --- a/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs +++ b/csharp/Lib/Devices/Trumpf/TruConvertDc/TruConvertDcStatus.cs @@ -1,6 +1,7 @@ -using InnovEnergy.Lib.Devices.Trumpf.TruConvert; -using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.StatusApi.Devices; +using InnovEnergy.Lib.StatusApi; +using InnovEnergy.Lib.Units; +using InnovEnergy.Lib.Units.Composite; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; @@ -8,20 +9,24 @@ using AlarmMessages = IReadOnlyList; using WarningMessages = IReadOnlyList; using DcCurrentLimitStates = IReadOnlyList; -public record TruConvertDcStatus +public record TruConvertDcStatus ( - DcConnection Dc, - MainState MainState, - UInt16 NumberOfConnectedSlaves, - UInt16 NumberOfConnectedSubSlaves, - Decimal BatteryVoltage, - Decimal BatteryCurrent, - Decimal TotalDcPower, - DcCurrentLimitStates StatusOfCurrentLimiting, - Decimal OverloadCapacity, - Decimal DcDcInletTemperature, - AlarmMessages Alarms, - WarningMessages Warnings, - Boolean PowerOperation -):DcDevice(Dc) -{} \ No newline at end of file + DcBus DcLeft, + DcBus DcRight, + State MainState, + Power TotalDcPower, // TODO: necessary? + State StatusOfCurrentLimiting, + Decimal OverloadCapacity, + Temperature DcDcInletTemperature, + State Alarms, + State Warnings, + State PowerOperation + + // UInt16 NumberOfConnectedSlaves, // TODO: necessary? + // UInt16 NumberOfConnectedSubSlaves, // TODO: necessary? +) : + DcDcConverterStatus(DcLeft, DcRight) +{ + public static TruConvertDcStatus operator |(TruConvertDcStatus left, TruConvertDcStatus right) => OpParallel(left, right); + private static readonly Func OpParallel = Operators.Op("|"); +} \ No newline at end of file From 6f48b976218870809b38a4f09b42d10f14cdadf9 Mon Sep 17 00:00:00 2001 From: atef Date: Wed, 1 Mar 2023 13:23:16 +0100 Subject: [PATCH 040/114] fix some minor csproj settings --- csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj | 3 --- csharp/Lib/Victron/VeDBus/VeDBus.csproj | 5 ----- csharp/Lib/Victron/VictronVRM/VictronVRM.csproj | 5 ----- 3 files changed, 13 deletions(-) diff --git a/csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj b/csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj index c00eed4bb..1f571c26d 100644 --- a/csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj +++ b/csharp/App/RemoteSupportConsole/RemoteSupportConsole.csproj @@ -6,9 +6,6 @@ - - - diff --git a/csharp/Lib/Victron/VeDBus/VeDBus.csproj b/csharp/Lib/Victron/VeDBus/VeDBus.csproj index fe0000124..c7d6bf0a9 100644 --- a/csharp/Lib/Victron/VeDBus/VeDBus.csproj +++ b/csharp/Lib/Victron/VeDBus/VeDBus.csproj @@ -2,11 +2,6 @@ - - - latest - - diff --git a/csharp/Lib/Victron/VictronVRM/VictronVRM.csproj b/csharp/Lib/Victron/VictronVRM/VictronVRM.csproj index f37c8f354..c5a94a419 100644 --- a/csharp/Lib/Victron/VictronVRM/VictronVRM.csproj +++ b/csharp/Lib/Victron/VictronVRM/VictronVRM.csproj @@ -6,11 +6,6 @@ full - - - latest - - From be5999e0f0b521bbc6fa51de4b95ea136ba23092 Mon Sep 17 00:00:00 2001 From: atef Date: Wed, 1 Mar 2023 13:23:42 +0100 Subject: [PATCH 041/114] remove trailing 'require' --- .../Battery48TL/Battery48TLStatusRecord.cs | 26 +++++++++---------- csharp/Lib/StatusApi/BatteryStatus.cs | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs b/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs index 79bc1c7df..b9feb07d0 100644 --- a/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs +++ b/csharp/Lib/Devices/Battery48TL/Battery48TLStatusRecord.cs @@ -10,23 +10,23 @@ using T = Battery48TLStatus; [SuppressMessage("ReSharper", "InconsistentNaming")] public record Battery48TLStatus : BatteryStatus { - public required Voltage CellsVoltage { get; init; } + public Voltage CellsVoltage { get; init; } - public required Power MaxChargingPower { get; init; } - public required Power MaxDischargingPower { get; init; } + public Power MaxChargingPower { get; init; } + public Power MaxDischargingPower { get; init; } - public required State GreenLed { get; init; } - public required State AmberLed { get; init; } - public required State BlueLed { get; init; } - public required State RedLed { get; init; } + public State GreenLed { get; init; } + public State AmberLed { get; init; } + public State BlueLed { get; init; } + public State RedLed { get; init; } - public required State Warnings { get; init; } - public required State Alarms { get; init; } + public State Warnings { get; init; } + public State Alarms { get; init; } - public required State MainSwitchState { get; init; } // connected to bus | disconnected from bus - public required State HeaterState { get; init; } // heating | not heating - public required State EocState { get; init; } // EOC reached | EOC not reached - public required State TemperatureState { get; init; } // cold | operating temperature | overheated + public State MainSwitchState { get; init; } // connected to bus | disconnected from bus + public State HeaterState { get; init; } // heating | not heating + public State EocState { get; init; } // EOC reached | EOC not reached + public State TemperatureState { get; init; } // cold | operating temperature | overheated public static T operator |(T left, T right) => OpParallel(left, right); diff --git a/csharp/Lib/StatusApi/BatteryStatus.cs b/csharp/Lib/StatusApi/BatteryStatus.cs index 6c656b1c9..f8a0124d5 100644 --- a/csharp/Lib/StatusApi/BatteryStatus.cs +++ b/csharp/Lib/StatusApi/BatteryStatus.cs @@ -10,7 +10,7 @@ using T = BatteryStatus; [OpParallel] public partial record BatteryStatus : DeviceStatus, IDcConnection { - public DcBus Dc { get; init; } + public DcBus Dc { get; init; } public Percent Soc { get; init; } public Temperature Temperature { get; init; } } From 55048b3f99016ab58a974f68203a2afd6703d962 Mon Sep 17 00:00:00 2001 From: atef Date: Wed, 1 Mar 2023 13:35:33 +0100 Subject: [PATCH 042/114] lift EmuMeter to new StatusApi --- csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs | 106 +++++++++++------- csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs | 27 +---- 2 files changed, 72 insertions(+), 61 deletions(-) diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs index e4a766d30..ef3ba19ec 100644 --- a/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs +++ b/csharp/Lib/Devices/EmuMeter/EmuMeterDevice.cs @@ -1,3 +1,4 @@ +using DecimalMath; using InnovEnergy.Lib.Protocols.Modbus.Clients; using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.StatusApi.Connections; @@ -29,7 +30,9 @@ public class EmuMeterDevice return null; } } - private static Decimal GetPhi(Decimal cosPhi) => cosPhi.Clamp(-1m, 1m).Apply(ACos); + + + //private static Decimal GetPhi(Decimal cosPhi) => cosPhi.Clamp(-1m, 1m).Apply(ACos); private EmuMeterStatus TryReadStatus() { @@ -75,45 +78,70 @@ public class EmuMeterDevice var energyImportL3 = energyPhases[80 / 4] / 1000.0m; var energyExportL3 = energyPhases[100 / 4] / 1000.0m; + // Ac: new Ac3Bus + // ( + // new AcPhase( + // voltageL1N, + // currentL1, + // GetPhi(powerFactorL1) + // ), + // + // new AcPhase( + // voltageL2N, + // currentL2, + // GetPhi(powerFactorL2) + // ), + // + // new AcPhase( + // voltageL3N, + // currentL3, + // GetPhi(powerFactorL3) + // ), + // frequency + // ), + // activePowerL123, + // reactivePowerL123, + // apparentPowerL123, + // currentL123, + // voltageL1L2, + // voltageL2L3, + // voltageL3L1, + // energyImportL123, + // energyImportL1, + // energyImportL2, + // energyImportL3, + // energyExportL123, + // energyExportL1, + // energyExportL2, + // energyExportL3 + // ); + return new EmuMeterStatus - ( - Ac: new Ac3Bus - ( - new AcPhase( - voltageL1N, - currentL1, - GetPhi(powerFactorL1) - ), - - new AcPhase( - voltageL2N, - currentL2, - GetPhi(powerFactorL2) - ), - - new AcPhase( - voltageL3N, - currentL3, - GetPhi(powerFactorL3) - ), - frequency - ), - activePowerL123, - reactivePowerL123, - apparentPowerL123, - currentL123, - voltageL1L2, - voltageL2L3, - voltageL3L1, - energyImportL123, - energyImportL1, - energyImportL2, - energyImportL3, - energyExportL123, - energyExportL1, - energyExportL2, - energyExportL3 - ); + { + Ac = new Ac3Bus + { + Frequency = frequency, + L1 = new AcPhase + { + Current = currentL1, + Voltage = voltageL1N, + Phi = ATan2(reactivePowerL1, activePowerL1) // TODO: check that this works + }, + L2 = new AcPhase + { + Current = currentL2, + Voltage = voltageL2N, + Phi = ATan2(reactivePowerL2, activePowerL2) + }, + L3 = new AcPhase + { + Current = currentL3, + Voltage = voltageL3N, + Phi = ATan2(reactivePowerL3, activePowerL3) + } + } + }; + } } \ No newline at end of file diff --git a/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs b/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs index 3e629c15a..c1c9eb26e 100644 --- a/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs +++ b/csharp/Lib/Devices/EmuMeter/EmuMeterStatus.cs @@ -1,27 +1,10 @@ using InnovEnergy.Lib.StatusApi; -using InnovEnergy.Lib.StatusApi.Connections; -using InnovEnergy.Lib.Units.Composite; namespace InnovEnergy.Lib.Devices.EmuMeter; -public record EmuMeterStatus -( - Ac3Bus Ac, - Decimal ActivePowerL123, - Decimal ReactivePowerL123, - Decimal ApparentPowerL123, - Decimal CurrentL123, - Decimal VoltageL1L2, - Decimal VoltageL2L3, - Decimal VoltageL3L1, - Decimal EnergyImportL123, - Decimal EnergyImportL1, - Decimal EnergyImportL2, - Decimal EnergyImportL3, - Decimal EnergyExportL123, - Decimal EnergyExportL1, - Decimal EnergyExportL2, - Decimal EnergyExportL3 -):PowerMeterStatus(Ac) -{} +public record EmuMeterStatus : PowerMeterStatus +{ + // TODO add serial nb, (and other?) +} + From a3ccd2a537aa99bdf38fa4ba20a6842d38978e97 Mon Sep 17 00:00:00 2001 From: atef Date: Thu, 2 Mar 2023 15:14:22 +0100 Subject: [PATCH 043/114] Add more implicit conversions for State --- csharp/Lib/Units/State.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/csharp/Lib/Units/State.cs b/csharp/Lib/Units/State.cs index 3060186de..63b1c6d7c 100644 --- a/csharp/Lib/Units/State.cs +++ b/csharp/Lib/Units/State.cs @@ -15,12 +15,15 @@ public readonly struct State public State(params String[] values) : this((IReadOnlyList)values){} public State(params State[] states) : this((IReadOnlyList)states.SelectMany(s => s.Values).ToList()){} - public static implicit operator State(String s) => new State(s); - public static implicit operator State(Enum e) => new State(e.ToString()); - public static implicit operator State(Boolean s) => new State(s.ToString()); - public static implicit operator State(List s) => new State((IReadOnlyList)s); + public static implicit operator State(String s) => new(s); + public static implicit operator State(Enum e) => new(e.ToString()); + public static implicit operator State(Boolean s) => new(s.ToString()); + public static implicit operator State(List s) => new((IReadOnlyList)s); + public static implicit operator State(String[] s) => new((IReadOnlyList)s); + public static implicit operator State(List es) => new(es.Select(e => e.ToString()).ToArray()); + public static implicit operator State(Enum[] es) => new(es.Select(e => e.ToString()).ToArray()); - public static State operator |(State left, State right) => new State(left, right); + public static State operator |(State left, State right) => new(left, right); public override String ToString() => String.Join("; ", Values); } \ No newline at end of file From 8c3caa06d5e82214f11ad3d49de9fe6f181b5449 Mon Sep 17 00:00:00 2001 From: atef Date: Thu, 2 Mar 2023 15:22:00 +0100 Subject: [PATCH 044/114] Introduce number type --- csharp/Lib/Units/Number.cs | 13 +++++ csharp/Lib/Units/Number.generated.cs | 77 ++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 csharp/Lib/Units/Number.cs create mode 100644 csharp/Lib/Units/Number.generated.cs diff --git a/csharp/Lib/Units/Number.cs b/csharp/Lib/Units/Number.cs new file mode 100644 index 000000000..fdc9b3b42 --- /dev/null +++ b/csharp/Lib/Units/Number.cs @@ -0,0 +1,13 @@ +using InnovEnergy.Lib.Units.Generator; + + +namespace InnovEnergy.Lib.Units; + +[Sum] +public readonly partial struct Number +{ + public static String Unit => ""; + public static String Symbol => ""; + + public Number(Decimal value) => Value = value; +} \ No newline at end of file diff --git a/csharp/Lib/Units/Number.generated.cs b/csharp/Lib/Units/Number.generated.cs new file mode 100644 index 000000000..bfe8bcf8e --- /dev/null +++ b/csharp/Lib/Units/Number.generated.cs @@ -0,0 +1,77 @@ +#nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. +#define Sum + +using static System.Math; + +namespace InnovEnergy.Lib.Units; + +using T = Number; + +public readonly partial struct Number +{ + public Decimal Value { get; } + public override String ToString() => Value + Unit; + + // scalar multiplication + + public static T operator *(Decimal scalar, T t) => new T(scalar * t.Value); + public static T operator *(T t, Decimal scalar) => new T(scalar * t.Value); + public static T operator /(T t, Decimal scalar) => new T(t.Value / scalar); + + // parallel + + #if Sum + + public static T operator |(T left, T right) => new T(left.Value + right.Value); + public static T operator -(T t) => new T(-t.Value); + + #elif Mean + + public static T operator |(T left, T right) => new T((left.Value + right.Value)/2m); + + #elif Equal + + public static T operator |(T left, T right) + { + var d = Max(Abs(left.Value), Abs(right.Value)); + + if (d == 0m) + return new T(0m); + + var relativeError = Abs(left.Value - right.Value) / d; + + const Decimal maxRelativeError = 0.05m; + + if (relativeError > maxRelativeError) + throw new Exception($"{nameof(left)} and {nameof(right)} must be approximately equal.\n" + + $"Difference > {maxRelativeError * 100}% detected\n" + + $"{nameof(left)} : {left}\n" + + $"{nameof(right)}: {right}"); + + return new T((left.Value + right.Value) / 2m); + } + #endif + + // compare + + public static Boolean operator ==(T left, T right) => left.Value == right.Value; + public static Boolean operator !=(T left, T right) => left.Value != right.Value; + public static Boolean operator > (T left, T right) => left.Value > right.Value; + public static Boolean operator < (T left, T right) => left.Value < right.Value; + public static Boolean operator >=(T left, T right) => left.Value >= right.Value; + public static Boolean operator <=(T left, T right) => left.Value <= right.Value; + + // conversion + + public static implicit operator T(Decimal d) => new T(d); + public static implicit operator T(Double d) => new T((Decimal)d); + public static implicit operator T(Int32 i) => new T(i); + public static implicit operator Decimal(T t) => t.Value; + + // equality + + public Boolean Equals(T other) => Value == other.Value; + public override Boolean Equals(Object? obj) => obj is T other && Equals(other); + public override Int32 GetHashCode() => Value.GetHashCode(); + +} From 19188fa4307e550a45fcaf2f54512d132dfcf3cc Mon Sep 17 00:00:00 2001 From: atef Date: Thu, 2 Mar 2023 15:26:27 +0100 Subject: [PATCH 045/114] Implement IReadOnlyList for State --- csharp/Lib/Units/State.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/csharp/Lib/Units/State.cs b/csharp/Lib/Units/State.cs index 63b1c6d7c..90161a9b9 100644 --- a/csharp/Lib/Units/State.cs +++ b/csharp/Lib/Units/State.cs @@ -1,6 +1,8 @@ +using System.Collections; + namespace InnovEnergy.Lib.Units; -public readonly struct State +public readonly struct State : IReadOnlyList { public IReadOnlyList Values { get; } @@ -25,5 +27,11 @@ public readonly struct State public static State operator |(State left, State right) => new(left, right); + public IEnumerator GetEnumerator() => Values.GetEnumerator(); + public override String ToString() => String.Join("; ", Values); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public Int32 Count => Values.Count; + public String this[Int32 index] => Values[index]; } \ No newline at end of file From 8ae91198585305c44b9ae61303ef0c9dbcb54ae6 Mon Sep 17 00:00:00 2001 From: ig Date: Thu, 2 Mar 2023 17:15:10 +0100 Subject: [PATCH 046/114] Round Units to 3 significant digits by default (ToString). Add JsonConverters to generator --- csharp/App/SaliMax/src/Utils.cs | 2 +- csharp/Lib/Units/Angle.generated.cs | 21 +++++++++++++- csharp/Lib/Units/ApparentPower.generated.cs | 21 +++++++++++++- csharp/Lib/Units/Current.generated.cs | 21 +++++++++++++- csharp/Lib/Units/Frequency.generated.cs | 21 +++++++++++++- csharp/Lib/Units/Generator/Template.txt | 23 ++++++++++++++-- csharp/Lib/Units/Generator/generate.sh | 2 +- csharp/Lib/Units/Json/CurrentConverter.cs | 17 ------------ csharp/Lib/Units/Json/PowerConverter.cs | 17 ------------ csharp/Lib/Units/Json/ResistanceConverter.cs | 17 ------------ csharp/Lib/Units/Json/VoltageConverter.cs | 17 ------------ csharp/Lib/Units/Number.generated.cs | 21 +++++++++++++- csharp/Lib/Units/Power.cs | 1 - csharp/Lib/Units/Power.generated.cs | 21 +++++++++++++- csharp/Lib/Units/ReactivePower.generated.cs | 21 +++++++++++++- csharp/Lib/Units/Resistance.generated.cs | 21 +++++++++++++- csharp/Lib/Units/State.cs | 4 +-- csharp/Lib/Units/Temperature.generated.cs | 21 +++++++++++++- csharp/Lib/Units/Units.cs | 29 +++++++++++++------- csharp/Lib/Units/Voltage.generated.cs | 21 +++++++++++++- csharp/Lib/Utils/DecimalUtils.cs | 16 +++++++---- csharp/Lib/Utils/EnumerableUtils.cs | 4 +-- 22 files changed, 256 insertions(+), 103 deletions(-) delete mode 100644 csharp/Lib/Units/Json/CurrentConverter.cs delete mode 100644 csharp/Lib/Units/Json/PowerConverter.cs delete mode 100644 csharp/Lib/Units/Json/ResistanceConverter.cs delete mode 100644 csharp/Lib/Units/Json/VoltageConverter.cs diff --git a/csharp/App/SaliMax/src/Utils.cs b/csharp/App/SaliMax/src/Utils.cs index 4104b5384..1cf608f84 100644 --- a/csharp/App/SaliMax/src/Utils.cs +++ b/csharp/App/SaliMax/src/Utils.cs @@ -6,6 +6,6 @@ public static class Utils { public static Decimal Round3(this Decimal d) { - return DecimalUtils.RoundToSignificantFigures(d, 3); + return DecimalUtils.RoundToSignificantDigits(d, 3); } } \ No newline at end of file diff --git a/csharp/Lib/Units/Angle.generated.cs b/csharp/Lib/Units/Angle.generated.cs index f2317f977..0c1abd7e5 100644 --- a/csharp/Lib/Units/Angle.generated.cs +++ b/csharp/Lib/Units/Angle.generated.cs @@ -2,6 +2,9 @@ #define Sum using static System.Math; +using System.Text.Json; +using System.Text.Json.Serialization; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Units; @@ -10,7 +13,7 @@ using T = Angle; public readonly partial struct Angle { public Decimal Value { get; } - public override String ToString() => Value + Unit; + public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit; // scalar multiplication @@ -75,3 +78,19 @@ public readonly partial struct Angle public override Int32 GetHashCode() => Value.GetHashCode(); } + + +internal class AngleConverter : JsonConverter +{ + public override Angle Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new Angle(reader.GetDecimal()); + } + + public override void Write(Utf8JsonWriter writer, Angle value, JsonSerializerOptions options) + { + var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits); + + writer.WriteNumberValue(rounded); + } +} \ No newline at end of file diff --git a/csharp/Lib/Units/ApparentPower.generated.cs b/csharp/Lib/Units/ApparentPower.generated.cs index 0775151c9..ae632e889 100644 --- a/csharp/Lib/Units/ApparentPower.generated.cs +++ b/csharp/Lib/Units/ApparentPower.generated.cs @@ -2,6 +2,9 @@ #define Sum using static System.Math; +using System.Text.Json; +using System.Text.Json.Serialization; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Units; @@ -10,7 +13,7 @@ using T = ApparentPower; public readonly partial struct ApparentPower { public Decimal Value { get; } - public override String ToString() => Value + Unit; + public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit; // scalar multiplication @@ -75,3 +78,19 @@ public readonly partial struct ApparentPower public override Int32 GetHashCode() => Value.GetHashCode(); } + + +internal class ApparentPowerConverter : JsonConverter +{ + public override ApparentPower Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new ApparentPower(reader.GetDecimal()); + } + + public override void Write(Utf8JsonWriter writer, ApparentPower value, JsonSerializerOptions options) + { + var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits); + + writer.WriteNumberValue(rounded); + } +} \ No newline at end of file diff --git a/csharp/Lib/Units/Current.generated.cs b/csharp/Lib/Units/Current.generated.cs index 93e9bdbf7..1bb733666 100644 --- a/csharp/Lib/Units/Current.generated.cs +++ b/csharp/Lib/Units/Current.generated.cs @@ -2,6 +2,9 @@ #define Sum using static System.Math; +using System.Text.Json; +using System.Text.Json.Serialization; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Units; @@ -10,7 +13,7 @@ using T = Current; public readonly partial struct Current { public Decimal Value { get; } - public override String ToString() => Value + Unit; + public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit; // scalar multiplication @@ -75,3 +78,19 @@ public readonly partial struct Current public override Int32 GetHashCode() => Value.GetHashCode(); } + + +internal class CurrentConverter : JsonConverter +{ + public override Current Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new Current(reader.GetDecimal()); + } + + public override void Write(Utf8JsonWriter writer, Current value, JsonSerializerOptions options) + { + var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits); + + writer.WriteNumberValue(rounded); + } +} \ No newline at end of file diff --git a/csharp/Lib/Units/Frequency.generated.cs b/csharp/Lib/Units/Frequency.generated.cs index 9618c18bc..b1e8c6e65 100644 --- a/csharp/Lib/Units/Frequency.generated.cs +++ b/csharp/Lib/Units/Frequency.generated.cs @@ -2,6 +2,9 @@ #define Equal using static System.Math; +using System.Text.Json; +using System.Text.Json.Serialization; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Units; @@ -10,7 +13,7 @@ using T = Frequency; public readonly partial struct Frequency { public Decimal Value { get; } - public override String ToString() => Value + Unit; + public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit; // scalar multiplication @@ -75,3 +78,19 @@ public readonly partial struct Frequency public override Int32 GetHashCode() => Value.GetHashCode(); } + + +internal class FrequencyConverter : JsonConverter +{ + public override Frequency Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new Frequency(reader.GetDecimal()); + } + + public override void Write(Utf8JsonWriter writer, Frequency value, JsonSerializerOptions options) + { + var rounded = value.Value.RoundToSignificantDigits(Units.JsonSignificantDigits); + + writer.WriteNumberValue(rounded); + } +} \ No newline at end of file diff --git a/csharp/Lib/Units/Generator/Template.txt b/csharp/Lib/Units/Generator/Template.txt index c78a3fcc6..857ecad58 100644 --- a/csharp/Lib/Units/Generator/Template.txt +++ b/csharp/Lib/Units/Generator/Template.txt @@ -1,7 +1,10 @@ #nullable enable // Auto-generated code requires an explicit '#nullable' directive in source. -#define Type +#define AggregationType using static System.Math; +using System.Text.Json; +using System.Text.Json.Serialization; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.Lib.Units; @@ -10,7 +13,7 @@ using T = Template; public readonly partial struct Template { public Decimal Value { get; } - public override String ToString() => Value + Unit; + public override String ToString() => Value.RoundToSignificantDigits(Units.DisplaySignificantDigits) + Unit; // scalar multiplication @@ -75,3 +78,19 @@ public readonly partial struct Template public override Int32 GetHashCode() => Value.GetHashCode(); } + + +internal class TemplateConverter : JsonConverter