diff --git a/2024_config_D3_Demo.pdf b/2024_config_D3_Demo.pdf deleted file mode 100644 index 9a5e13b..0000000 Binary files a/2024_config_D3_Demo.pdf and /dev/null differ diff --git a/data/measurements/dummy_file b/data/measurements/dummy_file deleted file mode 100644 index c81b66a..0000000 --- a/data/measurements/dummy_file +++ /dev/null @@ -1 +0,0 @@ -Makes folder visible for git. \ No newline at end of file diff --git a/data/measurements/measurements.json b/data/measurements/measurements.json deleted file mode 100644 index a5dcda9..0000000 --- a/data/measurements/measurements.json +++ /dev/null @@ -1,2450 +0,0 @@ -{"unit": "pcc_p", "value": -39.213, "time": 1717757673.495} -{"unit": "pcc_q", "value": 11.626, "time": 1717757673.675} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757673.651} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757673.651} -{"unit": "pv319_p", "value": 10.346, "time": 1717757673.615} -{"unit": "pv319_q", "value": 0.128, "time": 1717757673.615} -{"unit": "pv330_p", "value": 14.682, "time": 1717757673.08} -{"unit": "pv330_q", "value": -0.181, "time": 1717757673.08} -{"unit": "battery_p", "value": -0.221, "time": 1717757673.627} -{"unit": "battery_q", "value": 0.035, "time": 1717757673.627} -{"unit": "b2b_p", "value": 8.929, "time": 1717757673.621} -{"unit": "b2b_q", "value": -3.018, "time": 1717757673.621} -{"unit": "gaia_p", "value": 5.307, "time": 1717757673.581} -{"unit": "gaia_q", "value": -8.944, "time": 1717757673.581} -{"unit": "pcc_p", "value": -39.035, "time": 1717757674.75} -{"unit": "pcc_q", "value": 11.581, "time": 1717757674.75} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757674.721} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757674.721} -{"unit": "pv319_p", "value": 10.337, "time": 1717757674.823} -{"unit": "pv319_q", "value": 0.134, "time": 1717757674.823} -{"unit": "pv330_p", "value": 14.73, "time": 1717757674.629} -{"unit": "pv330_q", "value": -0.184, "time": 1717757674.629} -{"unit": "battery_p", "value": -0.222, "time": 1717757674.842} -{"unit": "battery_q", "value": 0.038, "time": 1717757674.842} -{"unit": "b2b_p", "value": 8.94, "time": 1717757674.86} -{"unit": "b2b_q", "value": -3.036, "time": 1717757674.86} -{"unit": "gaia_p", "value": 4.815, "time": 1717757674.644} -{"unit": "gaia_q", "value": -8.781, "time": 1717757674.644} -{"unit": "pcc_p", "value": -39.157, "time": 1717757675.831} -{"unit": "pcc_q", "value": 11.586, "time": 1717757675.831} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757675.971} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757675.971} -{"unit": "pv319_p", "value": 10.338, "time": 1717757675.85} -{"unit": "pv319_q", "value": 0.138, "time": 1717757675.85} -{"unit": "pv330_p", "value": 14.713, "time": 1717757675.836} -{"unit": "pv330_q", "value": -0.187, "time": 1717757675.836} -{"unit": "battery_p", "value": -0.219, "time": 1717757675.642} -{"unit": "battery_q", "value": 0.036, "time": 1717757675.642} -{"unit": "b2b_p", "value": 8.932, "time": 1717757675.967} -{"unit": "b2b_q", "value": -3.029, "time": 1717757675.967} -{"unit": "gaia_p", "value": 5.056, "time": 1717757675.982} -{"unit": "gaia_q", "value": -8.854, "time": 1717757675.982} -{"unit": "pcc_p", "value": -39.942, "time": 1717757676.921} -{"unit": "pcc_q", "value": 11.93, "time": 1717757676.921} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757677.036} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757677.036} -{"unit": "pv319_p", "value": 10.339, "time": 1717757677.015} -{"unit": "pv319_q", "value": 0.132, "time": 1717757677.015} -{"unit": "pv330_p", "value": 14.744, "time": 1717757676.989} -{"unit": "pv330_q", "value": -0.182, "time": 1717757676.989} -{"unit": "battery_p", "value": -0.221, "time": 1717757676.892} -{"unit": "battery_q", "value": 0.036, "time": 1717757676.892} -{"unit": "b2b_p", "value": 8.929, "time": 1717757677.094} -{"unit": "b2b_q", "value": -3.023, "time": 1717757677.094} -{"unit": "gaia_p", "value": 5.4, "time": 1717757677.048} -{"unit": "gaia_q", "value": -9.027, "time": 1717757677.048} -{"unit": "pcc_p", "value": -39.724, "time": 1717757678.161} -{"unit": "pcc_q", "value": 11.803, "time": 1717757678.161} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757678.111} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757678.111} -{"unit": "pv319_p", "value": 10.297, "time": 1717757678.167} -{"unit": "pv319_q", "value": 0.129, "time": 1717757678.167} -{"unit": "pv330_p", "value": 14.744, "time": 1717757676.989} -{"unit": "pv330_q", "value": -0.182, "time": 1717757676.989} -{"unit": "battery_p", "value": -0.22, "time": 1717757678.122} -{"unit": "battery_q", "value": 0.037, "time": 1717757678.122} -{"unit": "b2b_p", "value": 8.938, "time": 1717757678.156} -{"unit": "b2b_q", "value": -3.047, "time": 1717757678.156} -{"unit": "gaia_p", "value": 5.857, "time": 1717757678.195} -{"unit": "gaia_q", "value": -9.185, "time": 1717757678.195} -{"unit": "pcc_p", "value": -39.44, "time": 1717757679.251} -{"unit": "pcc_q", "value": 11.731, "time": 1717757679.251} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757679.191} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757679.191} -{"unit": "pv319_p", "value": 10.189, "time": 1717757679.215} -{"unit": "pv319_q", "value": 0.125, "time": 1717757679.215} -{"unit": "pv330_p", "value": 14.708, "time": 1717757678.339} -{"unit": "pv330_q", "value": -0.191, "time": 1717757678.339} -{"unit": "battery_p", "value": -0.219, "time": 1717757679.342} -{"unit": "battery_q", "value": 0.034, "time": 1717757679.342} -{"unit": "b2b_p", "value": 8.939, "time": 1717757679.163} -{"unit": "b2b_q", "value": -3.039, "time": 1717757679.163} -{"unit": "gaia_p", "value": 5.344, "time": 1717757679.435} -{"unit": "gaia_q", "value": -8.975, "time": 1717757679.435} -{"unit": "pcc_p", "value": -38.688, "time": 1717757680.326} -{"unit": "pcc_q", "value": 11.422, "time": 1717757680.326} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757680.431} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757680.431} -{"unit": "pv319_p", "value": 10.214, "time": 1717757680.382} -{"unit": "pv319_q", "value": 0.132, "time": 1717757680.382} -{"unit": "pv330_p", "value": 14.71, "time": 1717757680.292} -{"unit": "pv330_q", "value": -0.186, "time": 1717757680.292} -{"unit": "battery_p", "value": -0.221, "time": 1717757680.162} -{"unit": "battery_q", "value": 0.036, "time": 1717757680.162} -{"unit": "b2b_p", "value": 8.938, "time": 1717757680.46} -{"unit": "b2b_q", "value": -3.008, "time": 1717757680.46} -{"unit": "gaia_p", "value": 4.126, "time": 1717757680.448} -{"unit": "gaia_q", "value": -8.495, "time": 1717757680.448} -{"unit": "pcc_p", "value": -38.295, "time": 1717757681.421} -{"unit": "pcc_q", "value": 11.305, "time": 1717757681.596} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757681.511} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757681.511} -{"unit": "pv319_p", "value": 10.258, "time": 1717757681.523} -{"unit": "pv319_q", "value": 0.125, "time": 1717757681.523} -{"unit": "pv330_p", "value": 14.732, "time": 1717757681.334} -{"unit": "pv330_q", "value": -0.179, "time": 1717757681.334} -{"unit": "battery_p", "value": -0.221, "time": 1717757681.392} -{"unit": "battery_q", "value": 0.037, "time": 1717757681.392} -{"unit": "b2b_p", "value": 8.938, "time": 1717757681.364} -{"unit": "b2b_q", "value": -3.031, "time": 1717757681.686} -{"unit": "gaia_p", "value": 4.093, "time": 1717757681.585} -{"unit": "gaia_q", "value": -8.495, "time": 1717757681.585} -{"unit": "pcc_p", "value": -37.245, "time": 1717757682.671} -{"unit": "pcc_q", "value": 10.958, "time": 1717757682.671} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757682.581} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757682.756} -{"unit": "pv319_p", "value": 10.336, "time": 1717757682.557} -{"unit": "pv319_q", "value": 0.13, "time": 1717757682.557} -{"unit": "pv330_p", "value": 14.742, "time": 1717757682.556} -{"unit": "pv330_q", "value": -0.184, "time": 1717757682.556} -{"unit": "battery_p", "value": -0.221, "time": 1717757682.627} -{"unit": "battery_q", "value": 0.031, "time": 1717757682.627} -{"unit": "b2b_p", "value": 8.93, "time": 1717757681.686} -{"unit": "b2b_q", "value": -3.031, "time": 1717757681.686} -{"unit": "gaia_p", "value": 2.982, "time": 1717757682.779} -{"unit": "gaia_q", "value": -8.139, "time": 1717757682.779} -{"unit": "pcc_p", "value": -37.044, "time": 1717757683.756} -{"unit": "pcc_q", "value": 10.886, "time": 1717757683.756} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757683.846} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757683.846} -{"unit": "pv319_p", "value": 10.341, "time": 1717757683.726} -{"unit": "pv319_q", "value": 0.13, "time": 1717757683.726} -{"unit": "pv330_p", "value": 14.765, "time": 1717757683.558} -{"unit": "pv330_q", "value": -0.185, "time": 1717757683.558} -{"unit": "battery_p", "value": -0.221, "time": 1717757683.857} -{"unit": "battery_q", "value": 0.037, "time": 1717757683.857} -{"unit": "b2b_p", "value": 8.939, "time": 1717757683.781} -{"unit": "b2b_q", "value": -3.004, "time": 1717757683.781} -{"unit": "gaia_p", "value": 3.424, "time": 1717757683.713} -{"unit": "gaia_q", "value": -8.265, "time": 1717757683.713} -{"unit": "pcc_p", "value": -37.277, "time": 1717757684.826} -{"unit": "pcc_q", "value": 10.95, "time": 1717757684.826} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757684.936} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757684.936} -{"unit": "pv319_p", "value": 10.35, "time": 1717757684.829} -{"unit": "pv319_q", "value": 0.135, "time": 1717757685.032} -{"unit": "pv330_p", "value": 14.768, "time": 1717757684.979} -{"unit": "pv330_q", "value": -0.185, "time": 1717757684.979} -{"unit": "battery_p", "value": -0.221, "time": 1717757684.682} -{"unit": "battery_q", "value": 0.036, "time": 1717757684.682} -{"unit": "b2b_p", "value": 8.925, "time": 1717757685.001} -{"unit": "b2b_q", "value": -3.027, "time": 1717757685.001} -{"unit": "gaia_p", "value": 2.892, "time": 1717757684.881} -{"unit": "gaia_q", "value": -8.096, "time": 1717757684.881} -{"unit": "pcc_p", "value": -37.372, "time": 1717757686.111} -{"unit": "pcc_q", "value": 10.957, "time": 1717757686.111} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757686.006} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757686.006} -{"unit": "pv319_p", "value": 10.346, "time": 1717757685.967} -{"unit": "pv319_q", "value": 0.139, "time": 1717757685.967} -{"unit": "pv330_p", "value": 14.776, "time": 1717757686.19} -{"unit": "pv330_q", "value": -0.184, "time": 1717757686.19} -{"unit": "battery_p", "value": -0.221, "time": 1717757685.922} -{"unit": "battery_q", "value": 0.038, "time": 1717757685.922} -{"unit": "b2b_p", "value": 8.933, "time": 1717757686.205} -{"unit": "b2b_q", "value": -3.035, "time": 1717757686.205} -{"unit": "gaia_p", "value": 2.478, "time": 1717757686.256} -{"unit": "gaia_q", "value": -7.991, "time": 1717757686.256} -{"unit": "pcc_p", "value": -36.235, "time": 1717757687.261} -{"unit": "pcc_q", "value": 10.639, "time": 1717757687.261} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757687.256} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757687.256} -{"unit": "pv319_p", "value": 10.351, "time": 1717757687.133} -{"unit": "pv319_q", "value": 0.141, "time": 1717757687.133} -{"unit": "pv330_p", "value": 14.825, "time": 1717757687.247} -{"unit": "pv330_q", "value": -0.188, "time": 1717757687.247} -{"unit": "battery_p", "value": -0.221, "time": 1717757687.157} -{"unit": "battery_q", "value": 0.039, "time": 1717757687.157} -{"unit": "b2b_p", "value": 8.933, "time": 1717757686.797} -{"unit": "b2b_q", "value": -3.021, "time": 1717757686.797} -{"unit": "gaia_p", "value": 2.879, "time": 1717757687.184} -{"unit": "gaia_q", "value": -8.133, "time": 1717757687.184} -{"unit": "pcc_p", "value": -36.108, "time": 1717757688.341} -{"unit": "pcc_q", "value": 10.658, "time": 1717757688.341} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757688.341} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757688.341} -{"unit": "pv319_p", "value": 10.352, "time": 1717757688.178} -{"unit": "pv319_q", "value": 0.132, "time": 1717757688.178} -{"unit": "pv330_p", "value": 14.744, "time": 1717757687.559} -{"unit": "pv330_q", "value": -0.19, "time": 1717757687.559} -{"unit": "battery_p", "value": -0.222, "time": 1717757688.367} -{"unit": "battery_q", "value": 0.035, "time": 1717757688.367} -{"unit": "b2b_p", "value": 8.934, "time": 1717757688.461} -{"unit": "b2b_q", "value": -3.045, "time": 1717757688.461} -{"unit": "gaia_p", "value": 1.72, "time": 1717757688.431} -{"unit": "gaia_q", "value": -7.804, "time": 1717757688.431} -{"unit": "pcc_p", "value": -35.994, "time": 1717757689.426} -{"unit": "pcc_q", "value": 10.642, "time": 1717757689.426} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757689.486} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757689.486} -{"unit": "pv319_p", "value": 10.329, "time": 1717757689.57} -{"unit": "pv319_q", "value": 0.132, "time": 1717757689.57} -{"unit": "pv330_p", "value": 14.809, "time": 1717757689.388} -{"unit": "pv330_q", "value": -0.179, "time": 1717757689.388} -{"unit": "battery_p", "value": -0.222, "time": 1717757689.572} -{"unit": "battery_q", "value": 0.039, "time": 1717757689.572} -{"unit": "b2b_p", "value": 8.935, "time": 1717757689.663} -{"unit": "b2b_q", "value": -3.061, "time": 1717757689.663} -{"unit": "gaia_p", "value": 1.688, "time": 1717757689.558} -{"unit": "gaia_q", "value": -7.804, "time": 1717757689.558} -{"unit": "pcc_p", "value": -35.921, "time": 1717757690.676} -{"unit": "pcc_q", "value": 10.647, "time": 1717757690.676} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757690.726} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757690.726} -{"unit": "pv319_p", "value": 10.339, "time": 1717757690.58} -{"unit": "pv319_q", "value": 0.135, "time": 1717757690.58} -{"unit": "pv330_p", "value": 14.817, "time": 1717757690.647} -{"unit": "pv330_q", "value": -0.185, "time": 1717757690.647} -{"unit": "battery_p", "value": -0.222, "time": 1717757690.412} -{"unit": "battery_q", "value": 0.039, "time": 1717757690.412} -{"unit": "b2b_p", "value": 8.934, "time": 1717757690.628} -{"unit": "b2b_q", "value": -3.033, "time": 1717757690.82} -{"unit": "gaia_p", "value": 1.572, "time": 1717757690.698} -{"unit": "gaia_q", "value": -7.803, "time": 1717757690.698} -{"unit": "pcc_p", "value": -36.268, "time": 1717757691.776} -{"unit": "pcc_q", "value": 10.735, "time": 1717757691.776} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757691.786} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757691.786} -{"unit": "pv319_p", "value": 10.34, "time": 1717757691.752} -{"unit": "pv319_q", "value": 0.131, "time": 1717757691.752} -{"unit": "pv330_p", "value": 14.82, "time": 1717757691.788} -{"unit": "pv330_q", "value": -0.189, "time": 1717757691.788} -{"unit": "battery_p", "value": -0.222, "time": 1717757691.637} -{"unit": "battery_q", "value": 0.038, "time": 1717757691.637} -{"unit": "b2b_p", "value": 8.934, "time": 1717757691.535} -{"unit": "b2b_q", "value": -3.027, "time": 1717757691.535} -{"unit": "gaia_p", "value": 2.109, "time": 1717757691.915} -{"unit": "gaia_q", "value": -7.952, "time": 1717757691.915} -{"unit": "pcc_p", "value": -36.291, "time": 1717757692.866} -{"unit": "pcc_q", "value": 10.723, "time": 1717757692.866} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757692.871} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757692.871} -{"unit": "pv319_p", "value": 10.327, "time": 1717757692.826} -{"unit": "pv319_q", "value": 0.126, "time": 1717757692.826} -{"unit": "pv330_p", "value": 14.833, "time": 1717757692.757} -{"unit": "pv330_q", "value": -0.184, "time": 1717757692.757} -{"unit": "battery_p", "value": -0.221, "time": 1717757692.912} -{"unit": "battery_q", "value": 0.038, "time": 1717757692.912} -{"unit": "b2b_p", "value": 8.931, "time": 1717757692.677} -{"unit": "b2b_q", "value": -3.035, "time": 1717757692.677} -{"unit": "gaia_p", "value": 2.007, "time": 1717757693.114} -{"unit": "gaia_q", "value": -7.895, "time": 1717757693.114} -{"unit": "pcc_p", "value": -35.871, "time": 1717757694.136} -{"unit": "pcc_q", "value": 10.603, "time": 1717757694.136} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757694.126} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757694.126} -{"unit": "pv319_p", "value": 10.345, "time": 1717757693.968} -{"unit": "pv319_q", "value": 0.124, "time": 1717757693.968} -{"unit": "pv330_p", "value": 14.835, "time": 1717757694.153} -{"unit": "pv330_q", "value": -0.178, "time": 1717757694.153} -{"unit": "battery_p", "value": -0.221, "time": 1717757694.137} -{"unit": "battery_q", "value": 0.039, "time": 1717757694.137} -{"unit": "b2b_p", "value": 8.93, "time": 1717757694.207} -{"unit": "b2b_q", "value": -3.041, "time": 1717757694.207} -{"unit": "gaia_p", "value": 1.505, "time": 1717757694.252} -{"unit": "gaia_q", "value": -7.752, "time": 1717757694.252} -{"unit": "pcc_p", "value": -35.301, "time": 1717757695.216} -{"unit": "pcc_q", "value": 10.502, "time": 1717757695.216} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757695.201} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757695.201} -{"unit": "pv319_p", "value": 10.3, "time": 1717757695.177} -{"unit": "pv319_q", "value": 0.119, "time": 1717757695.177} -{"unit": "pv330_p", "value": 14.87, "time": 1717757695.051} -{"unit": "pv330_q", "value": -0.178, "time": 1717757695.051} -{"unit": "battery_p", "value": -0.222, "time": 1717757694.962} -{"unit": "battery_q", "value": 0.038, "time": 1717757694.962} -{"unit": "b2b_p", "value": 8.921, "time": 1717757695.221} -{"unit": "b2b_q", "value": -3.035, "time": 1717757695.221} -{"unit": "gaia_p", "value": 1.016, "time": 1717757694.999} -{"unit": "gaia_q", "value": -7.676, "time": 1717757695.38} -{"unit": "pcc_p", "value": -35.333, "time": 1717757696.306} -{"unit": "pcc_q", "value": 10.511, "time": 1717757696.306} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757696.271} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757696.271} -{"unit": "pv319_p", "value": 10.382, "time": 1717757696.177} -{"unit": "pv319_q", "value": 0.105, "time": 1717757696.177} -{"unit": "pv330_p", "value": 14.83, "time": 1717757696.374} -{"unit": "pv330_q", "value": -0.187, "time": 1717757696.374} -{"unit": "battery_p", "value": -0.222, "time": 1717757696.182} -{"unit": "battery_q", "value": 0.038, "time": 1717757696.182} -{"unit": "b2b_p", "value": 8.933, "time": 1717757696.371} -{"unit": "b2b_q", "value": -3.034, "time": 1717757696.371} -{"unit": "gaia_p", "value": 1.241, "time": 1717757696.495} -{"unit": "gaia_q", "value": -7.693, "time": 1717757696.495} -{"unit": "pcc_p", "value": -35.627, "time": 1717757697.411} -{"unit": "pcc_q", "value": 10.561, "time": 1717757697.411} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757697.506} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757697.506} -{"unit": "pv319_p", "value": 10.388, "time": 1717757697.222} -{"unit": "pv319_q", "value": 0.121, "time": 1717757697.222} -{"unit": "pv330_p", "value": 14.84, "time": 1717757697.538} -{"unit": "pv330_q", "value": -0.179, "time": 1717757697.538} -{"unit": "battery_p", "value": -0.221, "time": 1717757697.402} -{"unit": "battery_q", "value": 0.039, "time": 1717757697.402} -{"unit": "b2b_p", "value": 8.93, "time": 1717757697.386} -{"unit": "b2b_q", "value": -3.03, "time": 1717757697.386} -{"unit": "gaia_p", "value": 1.425, "time": 1717757697.524} -{"unit": "gaia_q", "value": -7.762, "time": 1717757697.524} -{"unit": "pcc_p", "value": -36.313, "time": 1717757698.516} -{"unit": "pcc_q", "value": 10.771, "time": 1717757698.516} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757698.596} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757698.596} -{"unit": "pv319_p", "value": 10.382, "time": 1717757698.618} -{"unit": "pv319_q", "value": 0.118, "time": 1717757698.618} -{"unit": "pv330_p", "value": 14.866, "time": 1717757698.657} -{"unit": "pv330_q", "value": -0.187, "time": 1717757698.657} -{"unit": "battery_p", "value": -0.222, "time": 1717757698.627} -{"unit": "battery_q", "value": 0.039, "time": 1717757698.627} -{"unit": "b2b_p", "value": 8.931, "time": 1717757697.661} -{"unit": "b2b_q", "value": -3.057, "time": 1717757697.661} -{"unit": "gaia_p", "value": 1.294, "time": 1717757698.649} -{"unit": "gaia_q", "value": -7.706, "time": 1717757698.649} -{"unit": "pcc_p", "value": -37.016, "time": 1717757699.601} -{"unit": "pcc_q", "value": 10.957, "time": 1717757699.601} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757699.666} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757699.666} -{"unit": "pv319_p", "value": 10.397, "time": 1717757699.769} -{"unit": "pv319_q", "value": 0.116, "time": 1717757699.769} -{"unit": "pv330_p", "value": 14.853, "time": 1717757699.796} -{"unit": "pv330_q", "value": -0.19, "time": 1717757699.796} -{"unit": "battery_p", "value": -0.222, "time": 1717757699.452} -{"unit": "battery_q", "value": 0.039, "time": 1717757699.452} -{"unit": "b2b_p", "value": 8.929, "time": 1717757699.708} -{"unit": "b2b_q", "value": -3.053, "time": 1717757699.708} -{"unit": "gaia_p", "value": 2.615, "time": 1717757699.691} -{"unit": "gaia_q", "value": -8.118, "time": 1717757699.691} -{"unit": "pcc_p", "value": -36.909, "time": 1717757700.866} -{"unit": "pcc_q", "value": 10.832, "time": 1717757700.866} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757700.746} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757700.746} -{"unit": "pv319_p", "value": 10.363, "time": 1717757700.767} -{"unit": "pv319_q", "value": 0.11, "time": 1717757700.767} -{"unit": "pv330_p", "value": 14.865, "time": 1717757700.936} -{"unit": "pv330_q", "value": -0.188, "time": 1717757700.936} -{"unit": "battery_p", "value": -0.219, "time": 1717757700.702} -{"unit": "battery_q", "value": 0.037, "time": 1717757700.702} -{"unit": "b2b_p", "value": 8.939, "time": 1717757700.764} -{"unit": "b2b_q", "value": -3.046, "time": 1717757700.764} -{"unit": "gaia_p", "value": 2.565, "time": 1717757700.863} -{"unit": "gaia_q", "value": -8.043, "time": 1717757700.863} -{"unit": "pcc_p", "value": -37.357, "time": 1717757701.936} -{"unit": "pcc_q", "value": 10.957, "time": 1717757701.936} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757701.996} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757701.996} -{"unit": "pv319_p", "value": 10.403, "time": 1717757701.815} -{"unit": "pv319_q", "value": 0.117, "time": 1717757701.815} -{"unit": "pv330_p", "value": 14.852, "time": 1717757701.779} -{"unit": "pv330_q", "value": -0.185, "time": 1717757701.779} -{"unit": "battery_p", "value": -0.22, "time": 1717757701.937} -{"unit": "battery_q", "value": 0.035, "time": 1717757701.937} -{"unit": "b2b_p", "value": 8.929, "time": 1717757701.964} -{"unit": "b2b_q", "value": -3.025, "time": 1717757701.964} -{"unit": "gaia_p", "value": 3.233, "time": 1717757702.051} -{"unit": "gaia_q", "value": -8.245, "time": 1717757702.051} -{"unit": "pcc_p", "value": -37.679, "time": 1717757703.021} -{"unit": "pcc_q", "value": 11.045, "time": 1717757703.021} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757703.056} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757703.056} -{"unit": "pv319_p", "value": 10.399, "time": 1717757702.946} -{"unit": "pv319_q", "value": 0.124, "time": 1717757702.946} -{"unit": "pv330_p", "value": 14.857, "time": 1717757703.06} -{"unit": "pv330_q", "value": -0.188, "time": 1717757703.06} -{"unit": "battery_p", "value": -0.222, "time": 1717757703.182} -{"unit": "battery_q", "value": 0.032, "time": 1717757703.182} -{"unit": "b2b_p", "value": 8.927, "time": 1717757702.169} -{"unit": "b2b_q", "value": -3.046, "time": 1717757703.325} -{"unit": "gaia_p", "value": 3.147, "time": 1717757703.185} -{"unit": "gaia_q", "value": -8.22, "time": 1717757703.185} -{"unit": "pcc_p", "value": -37.605, "time": 1717757704.351} -{"unit": "pcc_q", "value": 11.043, "time": 1717757704.351} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757704.321} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757704.321} -{"unit": "pv319_p", "value": 10.373, "time": 1717757704.377} -{"unit": "pv319_q", "value": 0.125, "time": 1717757704.377} -{"unit": "pv330_p", "value": 14.874, "time": 1717757704.388} -{"unit": "pv330_q", "value": -0.182, "time": 1717757704.388} -{"unit": "battery_p", "value": -0.221, "time": 1717757704.412} -{"unit": "battery_q", "value": 0.037, "time": 1717757704.412} -{"unit": "b2b_p", "value": 8.932, "time": 1717757704.575} -{"unit": "b2b_q", "value": -3.043, "time": 1717757704.575} -{"unit": "gaia_p", "value": 3.822, "time": 1717757704.387} -{"unit": "gaia_q", "value": -8.462, "time": 1717757704.387} -{"unit": "pcc_p", "value": -37.76, "time": 1717757705.596} -{"unit": "pcc_q", "value": 11.1, "time": 1717757705.596} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757705.666} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757705.666} -{"unit": "pv319_p", "value": 10.41, "time": 1717757705.577} -{"unit": "pv319_q", "value": 0.124, "time": 1717757705.577} -{"unit": "pv330_p", "value": 14.882, "time": 1717757705.589} -{"unit": "pv330_q", "value": -0.184, "time": 1717757705.589} -{"unit": "battery_p", "value": -0.222, "time": 1717757705.642} -{"unit": "battery_q", "value": 0.037, "time": 1717757705.642} -{"unit": "b2b_p", "value": 8.93, "time": 1717757705.676} -{"unit": "b2b_q", "value": -3.035, "time": 1717757705.676} -{"unit": "gaia_p", "value": 3.533, "time": 1717757705.648} -{"unit": "gaia_q", "value": -8.385, "time": 1717757705.648} -{"unit": "pcc_p", "value": -37.908, "time": 1717757706.666} -{"unit": "pcc_q", "value": 11.163, "time": 1717757706.666} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757706.751} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757706.751} -{"unit": "pv319_p", "value": 10.403, "time": 1717757706.544} -{"unit": "pv319_q", "value": 0.127, "time": 1717757706.544} -{"unit": "pv330_p", "value": 14.883, "time": 1717757706.78} -{"unit": "pv330_q", "value": -0.189, "time": 1717757706.78} -{"unit": "battery_p", "value": -0.221, "time": 1717757706.882} -{"unit": "battery_q", "value": 0.038, "time": 1717757706.882} -{"unit": "b2b_p", "value": 8.929, "time": 1717757706.735} -{"unit": "b2b_q", "value": -2.994, "time": 1717757706.966} -{"unit": "gaia_p", "value": 4.305, "time": 1717757706.896} -{"unit": "gaia_q", "value": -8.504, "time": 1717757706.896} -{"unit": "pcc_p", "value": -7.693, "time": 1717757707.941} -{"unit": "pcc_q", "value": 4.983, "time": 1717757707.941} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757708.011} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757708.011} -{"unit": "pv319_p", "value": 10.403, "time": 1717757708.024} -{"unit": "pv319_q", "value": 0.126, "time": 1717757708.024} -{"unit": "pv330_p", "value": 14.844, "time": 1717757707.343} -{"unit": "pv330_q", "value": -0.172, "time": 1717757707.343} -{"unit": "battery_p", "value": -0.222, "time": 1717757707.697} -{"unit": "battery_q", "value": 0.037, "time": 1717757707.697} -{"unit": "b2b_p", "value": -20.043, "time": 1717757707.589} -{"unit": "b2b_q", "value": 2.447, "time": 1717757707.589} -{"unit": "gaia_p", "value": 3.778, "time": 1717757707.897} -{"unit": "gaia_q", "value": -8.051, "time": 1717757707.897} -{"unit": "pcc_p", "value": -3.233, "time": 1717757709.021} -{"unit": "pcc_q", "value": 2.149, "time": 1717757709.021} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757709.081} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757709.081} -{"unit": "pv319_p", "value": 10.411, "time": 1717757708.976} -{"unit": "pv319_q", "value": 0.13, "time": 1717757708.976} -{"unit": "pv330_p", "value": 14.855, "time": 1717757709.149} -{"unit": "pv330_q", "value": -0.182, "time": 1717757709.149} -{"unit": "battery_p", "value": -0.222, "time": 1717757708.947} -{"unit": "battery_q", "value": 0.039, "time": 1717757708.947} -{"unit": "b2b_p", "value": -26.121, "time": 1717757709.166} -{"unit": "b2b_q", "value": 5.748, "time": 1717757709.166} -{"unit": "gaia_p", "value": 3.379, "time": 1717757709.05} -{"unit": "gaia_q", "value": -7.865, "time": 1717757709.05} -{"unit": "pcc_p", "value": -1.893, "time": 1717757710.106} -{"unit": "pcc_q", "value": 0.933, "time": 1717757710.286} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757710.161} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757710.161} -{"unit": "pv319_p", "value": 10.404, "time": 1717757710.323} -{"unit": "pv319_q", "value": 0.133, "time": 1717757710.323} -{"unit": "pv330_p", "value": 14.897, "time": 1717757710.176} -{"unit": "pv330_q", "value": -0.189, "time": 1717757710.176} -{"unit": "battery_p", "value": -0.222, "time": 1717757710.182} -{"unit": "battery_q", "value": 0.037, "time": 1717757710.182} -{"unit": "b2b_p", "value": -27.657, "time": 1717757710.261} -{"unit": "b2b_q", "value": 6.744, "time": 1717757710.261} -{"unit": "gaia_p", "value": 3.9, "time": 1717757710.296} -{"unit": "gaia_q", "value": -7.993, "time": 1717757710.296} -{"unit": "pcc_p", "value": -0.896, "time": 1717757711.351} -{"unit": "pcc_q", "value": 0.894, "time": 1717757711.351} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757711.406} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757711.406} -{"unit": "pv319_p", "value": 10.409, "time": 1717757711.425} -{"unit": "pv319_q", "value": 0.13, "time": 1717757711.425} -{"unit": "pv330_p", "value": 14.9, "time": 1717757711.338} -{"unit": "pv330_q", "value": -0.185, "time": 1717757711.338} -{"unit": "battery_p", "value": -0.221, "time": 1717757711.412} -{"unit": "battery_q", "value": 0.037, "time": 1717757711.412} -{"unit": "b2b_p", "value": -28.297, "time": 1717757711.411} -{"unit": "b2b_q", "value": 6.836, "time": 1717757711.411} -{"unit": "gaia_p", "value": 3.879, "time": 1717757711.523} -{"unit": "gaia_q", "value": -7.981, "time": 1717757711.523} -{"unit": "pcc_p", "value": -0.505, "time": 1717757712.406} -{"unit": "pcc_q", "value": 0.873, "time": 1717757712.406} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757712.466} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757712.466} -{"unit": "pv319_p", "value": 10.395, "time": 1717757712.521} -{"unit": "pv319_q", "value": 0.127, "time": 1717757712.521} -{"unit": "pv330_p", "value": 14.924, "time": 1717757712.34} -{"unit": "pv330_q", "value": -0.186, "time": 1717757712.34} -{"unit": "battery_p", "value": -0.222, "time": 1717757712.617} -{"unit": "battery_q", "value": 0.036, "time": 1717757712.617} -{"unit": "b2b_p", "value": -28.646, "time": 1717757712.593} -{"unit": "b2b_q", "value": 6.797, "time": 1717757712.593} -{"unit": "gaia_p", "value": 3.733, "time": 1717757712.587} -{"unit": "gaia_q", "value": -7.942, "time": 1717757712.587} -{"unit": "pcc_p", "value": 0.07, "time": 1717757713.661} -{"unit": "pcc_q", "value": 0.769, "time": 1717757713.661} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757713.536} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757713.536} -{"unit": "pv319_p", "value": 10.41, "time": 1717757713.616} -{"unit": "pv319_q", "value": 0.121, "time": 1717757713.616} -{"unit": "pv330_p", "value": 14.969, "time": 1717757713.701} -{"unit": "pv330_q", "value": -0.183, "time": 1717757713.701} -{"unit": "battery_p", "value": -0.222, "time": 1717757713.427} -{"unit": "battery_q", "value": 0.036, "time": 1717757713.427} -{"unit": "b2b_p", "value": -28.666, "time": 1717757712.966} -{"unit": "b2b_q", "value": 6.817, "time": 1717757712.966} -{"unit": "gaia_p", "value": 3.935, "time": 1717757713.649} -{"unit": "gaia_q", "value": -8.012, "time": 1717757713.649} -{"unit": "pcc_p", "value": 0.179, "time": 1717757714.736} -{"unit": "pcc_q", "value": 0.683, "time": 1717757714.736} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757714.796} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757714.796} -{"unit": "pv319_p", "value": 10.43, "time": 1717757714.78} -{"unit": "pv319_q", "value": 0.122, "time": 1717757714.78} -{"unit": "pv330_p", "value": 14.982, "time": 1717757714.8} -{"unit": "pv330_q", "value": -0.183, "time": 1717757714.8} -{"unit": "battery_p", "value": -0.221, "time": 1717757714.667} -{"unit": "battery_q", "value": 0.036, "time": 1717757714.667} -{"unit": "b2b_p", "value": -28.915, "time": 1717757714.711} -{"unit": "b2b_q", "value": 6.788, "time": 1717757714.711} -{"unit": "gaia_p", "value": 3.746, "time": 1717757714.715} -{"unit": "gaia_q", "value": -7.948, "time": 1717757714.715} -{"unit": "pcc_p", "value": 0.032, "time": 1717757716.001} -{"unit": "pcc_q", "value": 0.837, "time": 1717757716.001} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757715.866} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757716.046} -{"unit": "pv319_p", "value": 10.418, "time": 1717757716.008} -{"unit": "pv319_q", "value": 0.124, "time": 1717757716.008} -{"unit": "pv330_p", "value": 14.976, "time": 1717757715.937} -{"unit": "pv330_q", "value": -0.189, "time": 1717757715.937} -{"unit": "battery_p", "value": -0.221, "time": 1717757715.902} -{"unit": "battery_q", "value": 0.035, "time": 1717757715.902} -{"unit": "b2b_p", "value": -28.995, "time": 1717757715.986} -{"unit": "b2b_q", "value": 6.806, "time": 1717757715.986} -{"unit": "gaia_p", "value": 3.623, "time": 1717757716.114} -{"unit": "gaia_q", "value": -7.917, "time": 1717757716.114} -{"unit": "pcc_p", "value": 0.014, "time": 1717757717.081} -{"unit": "pcc_q", "value": 0.808, "time": 1717757717.081} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757717.126} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757717.126} -{"unit": "pv319_p", "value": 10.44, "time": 1717757717.133} -{"unit": "pv319_q", "value": 0.119, "time": 1717757717.133} -{"unit": "pv330_p", "value": 14.966, "time": 1717757717.189} -{"unit": "pv330_q", "value": -0.186, "time": 1717757717.189} -{"unit": "battery_p", "value": -0.22, "time": 1717757717.132} -{"unit": "battery_q", "value": 0.037, "time": 1717757717.132} -{"unit": "b2b_p", "value": -29.015, "time": 1717757717.061} -{"unit": "b2b_q", "value": 6.796, "time": 1717757717.061} -{"unit": "gaia_p", "value": 3.583, "time": 1717757717.096} -{"unit": "gaia_q", "value": -7.892, "time": 1717757717.096} -{"unit": "pcc_p", "value": -0.153, "time": 1717757718.161} -{"unit": "pcc_q", "value": 0.844, "time": 1717757718.161} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757718.206} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757718.206} -{"unit": "pv319_p", "value": 10.445, "time": 1717757718.325} -{"unit": "pv319_q", "value": 0.124, "time": 1717757718.325} -{"unit": "pv330_p", "value": 14.999, "time": 1717757718.028} -{"unit": "pv330_q", "value": -0.183, "time": 1717757718.028} -{"unit": "battery_p", "value": -0.221, "time": 1717757718.352} -{"unit": "battery_q", "value": 0.028, "time": 1717757718.352} -{"unit": "b2b_p", "value": -28.951, "time": 1717757718.252} -{"unit": "b2b_q", "value": 6.804, "time": 1717757718.252} -{"unit": "gaia_p", "value": 3.751, "time": 1717757718.296} -{"unit": "gaia_q", "value": -7.95, "time": 1717757718.296} -{"unit": "pcc_p", "value": -0.387, "time": 1717757719.296} -{"unit": "pcc_q", "value": 0.969, "time": 1717757719.296} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757719.451} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757719.451} -{"unit": "pv319_p", "value": 10.442, "time": 1717757719.326} -{"unit": "pv319_q", "value": 0.12, "time": 1717757719.326} -{"unit": "pv330_p", "value": 14.976, "time": 1717757719.389} -{"unit": "pv330_q", "value": -0.185, "time": 1717757719.389} -{"unit": "battery_p", "value": -0.221, "time": 1717757719.167} -{"unit": "battery_q", "value": 0.03, "time": 1717757719.167} -{"unit": "b2b_p", "value": -28.951, "time": 1717757718.252} -{"unit": "b2b_q", "value": 6.804, "time": 1717757718.252} -{"unit": "gaia_p", "value": 4.024, "time": 1717757719.37} -{"unit": "gaia_q", "value": -8.046, "time": 1717757719.37} -{"unit": "pcc_p", "value": -0.112, "time": 1717757720.556} -{"unit": "pcc_q", "value": 0.9, "time": 1717757720.556} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757720.541} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757720.541} -{"unit": "pv319_p", "value": 10.463, "time": 1717757720.616} -{"unit": "pv319_q", "value": 0.122, "time": 1717757720.616} -{"unit": "pv330_p", "value": 14.971, "time": 1717757720.579} -{"unit": "pv330_q", "value": -0.179, "time": 1717757720.579} -{"unit": "battery_p", "value": -0.221, "time": 1717757720.382} -{"unit": "battery_q", "value": 0.034, "time": 1717757720.382} -{"unit": "b2b_p", "value": -29.235, "time": 1717757720.621} -{"unit": "b2b_q", "value": 6.78, "time": 1717757720.621} -{"unit": "gaia_p", "value": 4.17, "time": 1717757720.45} -{"unit": "gaia_q", "value": -8.078, "time": 1717757720.45} -{"unit": "pcc_p", "value": -0.153, "time": 1717757721.626} -{"unit": "pcc_q", "value": 1.011, "time": 1717757721.626} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757721.676} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757721.676} -{"unit": "pv319_p", "value": 10.448, "time": 1717757721.747} -{"unit": "pv319_q", "value": 0.123, "time": 1717757721.747} -{"unit": "pv330_p", "value": 14.939, "time": 1717757721.673} -{"unit": "pv330_q", "value": -0.183, "time": 1717757721.673} -{"unit": "battery_p", "value": -0.222, "time": 1717757721.622} -{"unit": "battery_q", "value": 0.035, "time": 1717757721.622} -{"unit": "b2b_p", "value": -29.446, "time": 1717757721.62} -{"unit": "b2b_q", "value": 6.78, "time": 1717757721.82} -{"unit": "gaia_p", "value": 4.331, "time": 1717757721.782} -{"unit": "gaia_q", "value": -8.142, "time": 1717757721.782} -{"unit": "pcc_p", "value": -0.005, "time": 1717757722.702} -{"unit": "pcc_q", "value": 0.998, "time": 1717757722.702} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757722.756} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757722.756} -{"unit": "pv319_p", "value": 10.441, "time": 1717757722.553} -{"unit": "pv319_q", "value": 0.129, "time": 1717757722.553} -{"unit": "pv330_p", "value": 15.015, "time": 1717757721.98} -{"unit": "pv330_q", "value": -0.187, "time": 1717757721.98} -{"unit": "battery_p", "value": -0.221, "time": 1717757722.842} -{"unit": "battery_q", "value": 0.037, "time": 1717757722.842} -{"unit": "b2b_p", "value": -29.612, "time": 1717757722.5} -{"unit": "b2b_q", "value": 6.801, "time": 1717757722.5} -{"unit": "gaia_p", "value": 4.434, "time": 1717757722.984} -{"unit": "gaia_q", "value": -8.185, "time": 1717757722.984} -{"unit": "pcc_p", "value": 0.065, "time": 1717757723.982} -{"unit": "pcc_q", "value": 1.098, "time": 1717757723.982} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757724.011} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757724.011} -{"unit": "pv319_p", "value": 10.319, "time": 1717757723.97} -{"unit": "pv319_q", "value": 0.118, "time": 1717757723.97} -{"unit": "pv330_p", "value": 14.979, "time": 1717757723.935} -{"unit": "pv330_q", "value": -0.19, "time": 1717757723.935} -{"unit": "battery_p", "value": -0.221, "time": 1717757724.047} -{"unit": "battery_q", "value": 0.036, "time": 1717757724.047} -{"unit": "b2b_p", "value": -29.667, "time": 1717757724.072} -{"unit": "b2b_q", "value": 6.798, "time": 1717757724.072} -{"unit": "gaia_p", "value": 4.094, "time": 1717757724.065} -{"unit": "gaia_q", "value": -8.055, "time": 1717757724.065} -{"unit": "pcc_p", "value": -0.062, "time": 1717757725.052} -{"unit": "pcc_q", "value": 1.055, "time": 1717757725.052} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757725.081} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757725.081} -{"unit": "pv319_p", "value": 10.455, "time": 1717757725.078} -{"unit": "pv319_q", "value": 0.123, "time": 1717757725.078} -{"unit": "pv330_p", "value": 14.992, "time": 1717757724.974} -{"unit": "pv330_q", "value": -0.182, "time": 1717757725.229} -{"unit": "battery_p", "value": -0.221, "time": 1717757724.947} -{"unit": "battery_q", "value": 0.036, "time": 1717757724.947} -{"unit": "b2b_p", "value": -29.653, "time": 1717757725.073} -{"unit": "b2b_q", "value": 6.781, "time": 1717757725.261} -{"unit": "gaia_p", "value": 4.173, "time": 1717757725.25} -{"unit": "gaia_q", "value": -8.084, "time": 1717757725.25} -{"unit": "pcc_p", "value": -0.077, "time": 1717757726.147} -{"unit": "pcc_q", "value": 1.016, "time": 1717757726.147} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757726.151} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757726.151} -{"unit": "pv319_p", "value": 10.446, "time": 1717757726.217} -{"unit": "pv319_q", "value": 0.134, "time": 1717757726.217} -{"unit": "pv330_p", "value": 15.033, "time": 1717757726.19} -{"unit": "pv330_q", "value": -0.184, "time": 1717757726.19} -{"unit": "battery_p", "value": -0.221, "time": 1717757726.157} -{"unit": "battery_q", "value": 0.036, "time": 1717757726.157} -{"unit": "b2b_p", "value": -29.551, "time": 1717757726.268} -{"unit": "b2b_q", "value": 6.789, "time": 1717757726.268} -{"unit": "gaia_p", "value": 4.033, "time": 1717757726.229} -{"unit": "gaia_q", "value": -8.037, "time": 1717757726.229} -{"unit": "pcc_p", "value": 0.054, "time": 1717757727.397} -{"unit": "pcc_q", "value": 0.892, "time": 1717757727.397} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757727.391} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757727.391} -{"unit": "pv319_p", "value": 10.469, "time": 1717757727.133} -{"unit": "pv319_q", "value": 0.132, "time": 1717757727.133} -{"unit": "pv330_p", "value": 15.0, "time": 1717757727.228} -{"unit": "pv330_q", "value": -0.19, "time": 1717757727.228} -{"unit": "battery_p", "value": -0.222, "time": 1717757727.387} -{"unit": "battery_q", "value": 0.038, "time": 1717757727.387} -{"unit": "b2b_p", "value": -29.369, "time": 1717757727.501} -{"unit": "b2b_q", "value": 6.798, "time": 1717757727.501} -{"unit": "gaia_p", "value": 3.741, "time": 1717757727.482} -{"unit": "gaia_q", "value": -7.944, "time": 1717757727.482} -{"unit": "pcc_p", "value": -0.001, "time": 1717757728.477} -{"unit": "pcc_q", "value": 0.882, "time": 1717757728.477} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757728.466} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757728.466} -{"unit": "pv319_p", "value": 10.466, "time": 1717757728.578} -{"unit": "pv319_q", "value": 0.131, "time": 1717757728.578} -{"unit": "pv330_p", "value": 15.03, "time": 1717757728.582} -{"unit": "pv330_q", "value": -0.186, "time": 1717757728.582} -{"unit": "battery_p", "value": -0.221, "time": 1717757728.607} -{"unit": "battery_q", "value": 0.039, "time": 1717757728.607} -{"unit": "b2b_p", "value": -29.374, "time": 1717757727.862} -{"unit": "b2b_q", "value": 6.778, "time": 1717757727.862} -{"unit": "gaia_p", "value": 3.897, "time": 1717757728.296} -{"unit": "gaia_q", "value": -8.029, "time": 1717757728.659} -{"unit": "pcc_p", "value": -0.083, "time": 1717757729.552} -{"unit": "pcc_q", "value": 0.84, "time": 1717757729.552} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757729.556} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757729.556} -{"unit": "pv319_p", "value": 10.483, "time": 1717757729.626} -{"unit": "pv319_q", "value": 0.13, "time": 1717757729.626} -{"unit": "pv330_p", "value": 15.045, "time": 1717757729.717} -{"unit": "pv330_q", "value": -0.185, "time": 1717757729.717} -{"unit": "battery_p", "value": -0.221, "time": 1717757729.417} -{"unit": "battery_q", "value": 0.039, "time": 1717757729.417} -{"unit": "b2b_p", "value": -29.109, "time": 1717757729.574} -{"unit": "b2b_q", "value": 6.788, "time": 1717757729.574} -{"unit": "gaia_p", "value": 3.586, "time": 1717757729.462} -{"unit": "gaia_q", "value": -7.887, "time": 1717757729.462} -{"unit": "pcc_p", "value": 0.477, "time": 1717757730.802} -{"unit": "pcc_q", "value": 0.592, "time": 1717757730.802} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757730.806} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757730.806} -{"unit": "pv319_p", "value": 10.473, "time": 1717757730.777} -{"unit": "pv319_q", "value": 0.126, "time": 1717757730.777} -{"unit": "pv330_p", "value": 15.013, "time": 1717757730.849} -{"unit": "pv330_q", "value": -0.182, "time": 1717757730.849} -{"unit": "battery_p", "value": -0.22, "time": 1717757730.637} -{"unit": "battery_q", "value": 0.037, "time": 1717757730.637} -{"unit": "b2b_p", "value": -28.859, "time": 1717757730.864} -{"unit": "b2b_q", "value": 6.802, "time": 1717757730.864} -{"unit": "gaia_p", "value": 3.421, "time": 1717757730.785} -{"unit": "gaia_q", "value": -7.832, "time": 1717757730.785} -{"unit": "pcc_p", "value": 0.257, "time": 1717757731.877} -{"unit": "pcc_q", "value": 0.606, "time": 1717757731.877} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757731.896} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757731.896} -{"unit": "pv319_p", "value": 10.481, "time": 1717757731.747} -{"unit": "pv319_q", "value": 0.124, "time": 1717757731.747} -{"unit": "pv330_p", "value": 14.975, "time": 1717757731.975} -{"unit": "pv330_q", "value": -0.187, "time": 1717757731.975} -{"unit": "battery_p", "value": -0.222, "time": 1717757731.877} -{"unit": "battery_q", "value": 0.037, "time": 1717757731.877} -{"unit": "b2b_p", "value": -28.559, "time": 1717757731.972} -{"unit": "b2b_q", "value": 6.798, "time": 1717757731.972} -{"unit": "gaia_p", "value": 2.915, "time": 1717757731.987} -{"unit": "gaia_q", "value": -7.685, "time": 1717757731.987} -{"unit": "pcc_p", "value": -0.169, "time": 1717757732.972} -{"unit": "pcc_q", "value": 0.754, "time": 1717757732.972} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757732.976} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757732.976} -{"unit": "pv319_p", "value": 10.476, "time": 1717757732.828} -{"unit": "pv319_q", "value": 0.131, "time": 1717757732.828} -{"unit": "pv330_p", "value": 15.005, "time": 1717757733.03} -{"unit": "pv330_q", "value": -0.19, "time": 1717757733.03} -{"unit": "battery_p", "value": -0.222, "time": 1717757733.087} -{"unit": "battery_q", "value": 0.037, "time": 1717757733.087} -{"unit": "b2b_p", "value": -28.566, "time": 1717757732.807} -{"unit": "b2b_q", "value": 6.783, "time": 1717757732.807} -{"unit": "gaia_p", "value": 3.546, "time": 1717757733.064} -{"unit": "gaia_q", "value": -7.916, "time": 1717757733.064} -{"unit": "pcc_p", "value": 0.09, "time": 1717757734.052} -{"unit": "pcc_q", "value": 0.883, "time": 1717757734.227} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757734.241} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757734.241} -{"unit": "pv319_p", "value": 10.437, "time": 1717757734.217} -{"unit": "pv319_q", "value": 0.142, "time": 1717757734.217} -{"unit": "pv330_p", "value": 14.977, "time": 1717757734.357} -{"unit": "pv330_q", "value": -0.184, "time": 1717757734.357} -{"unit": "battery_p", "value": -0.222, "time": 1717757734.292} -{"unit": "battery_q", "value": 0.038, "time": 1717757734.292} -{"unit": "b2b_p", "value": -28.562, "time": 1717757733.341} -{"unit": "b2b_q", "value": 6.787, "time": 1717757733.341} -{"unit": "gaia_p", "value": 3.282, "time": 1717757734.174} -{"unit": "gaia_q", "value": -7.791, "time": 1717757734.174} -{"unit": "pcc_p", "value": 0.19, "time": 1717757735.562} -{"unit": "pcc_q", "value": 0.753, "time": 1717757735.562} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757735.496} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757735.496} -{"unit": "pv319_p", "value": 10.5, "time": 1717757735.587} -{"unit": "pv319_q", "value": 0.134, "time": 1717757735.587} -{"unit": "pv330_p", "value": 15.038, "time": 1717757735.639} -{"unit": "pv330_q", "value": -0.187, "time": 1717757735.639} -{"unit": "battery_p", "value": -0.223, "time": 1717757735.527} -{"unit": "battery_q", "value": 0.037, "time": 1717757735.527} -{"unit": "b2b_p", "value": -28.959, "time": 1717757735.832} -{"unit": "b2b_q", "value": 6.771, "time": 1717757735.832} -{"unit": "gaia_p", "value": 3.426, "time": 1717757735.801} -{"unit": "gaia_q", "value": -7.87, "time": 1717757735.801} -{"unit": "pcc_p", "value": -0.419, "time": 1717757736.817} -{"unit": "pcc_q", "value": 0.887, "time": 1717757737.007} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757736.922} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757736.922} -{"unit": "pv319_p", "value": 10.493, "time": 1717757736.751} -{"unit": "pv319_q", "value": 0.139, "time": 1717757736.751} -{"unit": "pv330_p", "value": 15.075, "time": 1717757736.978} -{"unit": "pv330_q", "value": -0.192, "time": 1717757736.978} -{"unit": "battery_p", "value": -0.22, "time": 1717757736.747} -{"unit": "battery_q", "value": 0.031, "time": 1717757737.157} -{"unit": "b2b_p", "value": -28.985, "time": 1717757737.063} -{"unit": "b2b_q", "value": 6.81, "time": 1717757737.063} -{"unit": "gaia_p", "value": 3.828, "time": 1717757737.059} -{"unit": "gaia_q", "value": -7.972, "time": 1717757737.059} -{"unit": "pcc_p", "value": -0.601, "time": 1717757738.092} -{"unit": "pcc_q", "value": 1.029, "time": 1717757738.092} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757738.241} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757738.241} -{"unit": "pv319_p", "value": 10.455, "time": 1717757738.129} -{"unit": "pv319_q", "value": 0.129, "time": 1717757738.129} -{"unit": "pv330_p", "value": 15.047, "time": 1717757738.342} -{"unit": "pv330_q", "value": -0.185, "time": 1717757738.342} -{"unit": "battery_p", "value": -0.221, "time": 1717757738.372} -{"unit": "battery_q", "value": 0.036, "time": 1717757738.372} -{"unit": "b2b_p", "value": -29.0, "time": 1717757738.164} -{"unit": "b2b_q", "value": 6.78, "time": 1717757738.164} -{"unit": "gaia_p", "value": 4.337, "time": 1717757738.196} -{"unit": "gaia_q", "value": -8.15, "time": 1717757738.196} -{"unit": "pcc_p", "value": 3.399, "time": 1717757739.527} -{"unit": "pcc_q", "value": 1.04, "time": 1717757739.527} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757739.491} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757739.491} -{"unit": "pv319_p", "value": 5.273, "time": 1717757739.524} -{"unit": "pv319_q", "value": 0.079, "time": 1717757739.524} -{"unit": "pv330_p", "value": 15.039, "time": 1717757739.541} -{"unit": "pv330_q", "value": -0.193, "time": 1717757739.541} -{"unit": "battery_p", "value": -0.221, "time": 1717757739.597} -{"unit": "battery_q", "value": 0.037, "time": 1717757739.597} -{"unit": "b2b_p", "value": -29.347, "time": 1717757739.632} -{"unit": "b2b_q", "value": 6.788, "time": 1717757739.632} -{"unit": "gaia_p", "value": 3.999, "time": 1717757739.648} -{"unit": "gaia_q", "value": -7.988, "time": 1717757739.648} -{"unit": "pcc_p", "value": -1.175, "time": 1717757740.612} -{"unit": "pcc_q", "value": 1.047, "time": 1717757740.612} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757740.561} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757740.561} -{"unit": "pv319_p", "value": 10.362, "time": 1717757740.577} -{"unit": "pv319_q", "value": 0.129, "time": 1717757740.577} -{"unit": "pv330_p", "value": 15.058, "time": 1717757740.69} -{"unit": "pv330_q", "value": -0.19, "time": 1717757740.69} -{"unit": "battery_p", "value": -0.221, "time": 1717757740.428} -{"unit": "battery_q", "value": 0.037, "time": 1717757740.428} -{"unit": "b2b_p", "value": -28.237, "time": 1717757740.708} -{"unit": "b2b_q", "value": 6.799, "time": 1717757740.708} -{"unit": "gaia_p", "value": 4.165, "time": 1717757740.78} -{"unit": "gaia_q", "value": -8.115, "time": 1717757740.78} -{"unit": "pcc_p", "value": -1.294, "time": 1717757741.692} -{"unit": "pcc_q", "value": 0.894, "time": 1717757741.692} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757741.811} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757741.811} -{"unit": "pv319_p", "value": 10.467, "time": 1717757741.745} -{"unit": "pv319_q", "value": 0.135, "time": 1717757741.745} -{"unit": "pv330_p", "value": 15.103, "time": 1717757741.759} -{"unit": "pv330_q", "value": -0.192, "time": 1717757741.759} -{"unit": "battery_p", "value": -0.221, "time": 1717757741.707} -{"unit": "battery_q", "value": 0.037, "time": 1717757741.707} -{"unit": "b2b_p", "value": -28.052, "time": 1717757741.858} -{"unit": "b2b_q", "value": 6.796, "time": 1717757741.858} -{"unit": "gaia_p", "value": 3.69, "time": 1717757741.849} -{"unit": "gaia_q", "value": -7.94, "time": 1717757741.849} -{"unit": "pcc_p", "value": -0.531, "time": 1717757742.972} -{"unit": "pcc_q", "value": 0.852, "time": 1717757742.972} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757742.886} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757742.886} -{"unit": "pv319_p", "value": 10.518, "time": 1717757742.838} -{"unit": "pv319_q", "value": 0.129, "time": 1717757742.838} -{"unit": "pv330_p", "value": 15.07, "time": 1717757742.559} -{"unit": "pv330_q", "value": -0.187, "time": 1717757742.559} -{"unit": "battery_p", "value": -0.222, "time": 1717757742.942} -{"unit": "battery_q", "value": 0.039, "time": 1717757742.942} -{"unit": "b2b_p", "value": -28.617, "time": 1717757742.721} -{"unit": "b2b_q", "value": 6.816, "time": 1717757742.721} -{"unit": "gaia_p", "value": 3.693, "time": 1717757743.097} -{"unit": "gaia_q", "value": -7.955, "time": 1717757743.097} -{"unit": "pcc_p", "value": -0.324, "time": 1717757744.057} -{"unit": "pcc_q", "value": 0.842, "time": 1717757744.057} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757744.136} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757744.136} -{"unit": "pv319_p", "value": 10.533, "time": 1717757744.124} -{"unit": "pv319_q", "value": 0.138, "time": 1717757744.124} -{"unit": "pv330_p", "value": 15.086, "time": 1717757744.181} -{"unit": "pv330_q", "value": -0.19, "time": 1717757744.181} -{"unit": "battery_p", "value": -0.223, "time": 1717757744.187} -{"unit": "battery_q", "value": 0.039, "time": 1717757744.187} -{"unit": "b2b_p", "value": -28.904, "time": 1717757744.065} -{"unit": "b2b_q", "value": 6.794, "time": 1717757744.065} -{"unit": "gaia_p", "value": 3.628, "time": 1717757743.918} -{"unit": "gaia_q", "value": -7.925, "time": 1717757743.918} -{"unit": "pcc_p", "value": -0.011, "time": 1717757745.157} -{"unit": "pcc_q", "value": 0.822, "time": 1717757745.157} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757745.221} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757745.221} -{"unit": "pv319_p", "value": 10.494, "time": 1717757745.146} -{"unit": "pv319_q", "value": 0.124, "time": 1717757745.146} -{"unit": "pv330_p", "value": 15.092, "time": 1717757745.26} -{"unit": "pv330_q", "value": -0.18, "time": 1717757745.26} -{"unit": "battery_p", "value": -0.221, "time": 1717757745.002} -{"unit": "battery_q", "value": 0.04, "time": 1717757745.002} -{"unit": "b2b_p", "value": -29.072, "time": 1717757745.226} -{"unit": "b2b_q", "value": 6.787, "time": 1717757745.226} -{"unit": "gaia_p", "value": 3.52, "time": 1717757745.051} -{"unit": "gaia_q", "value": -7.885, "time": 1717757745.051} -{"unit": "pcc_p", "value": 0.109, "time": 1717757746.232} -{"unit": "pcc_q", "value": 0.801, "time": 1717757746.232} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757746.316} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757746.316} -{"unit": "pv319_p", "value": 10.536, "time": 1717757746.169} -{"unit": "pv319_q", "value": 0.126, "time": 1717757746.169} -{"unit": "pv330_p", "value": 15.092, "time": 1717757746.358} -{"unit": "pv330_q", "value": -0.195, "time": 1717757746.358} -{"unit": "battery_p", "value": -0.22, "time": 1717757746.232} -{"unit": "battery_q", "value": 0.039, "time": 1717757746.232} -{"unit": "b2b_p", "value": -29.082, "time": 1717757746.231} -{"unit": "b2b_q", "value": 6.804, "time": 1717757746.231} -{"unit": "gaia_p", "value": 3.573, "time": 1717757746.312} -{"unit": "gaia_q", "value": -7.885, "time": 1717757746.312} -{"unit": "pcc_p", "value": 0.041, "time": 1717757747.322} -{"unit": "pcc_q", "value": 0.971, "time": 1717757747.507} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757747.381} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757747.381} -{"unit": "pv319_p", "value": 10.442, "time": 1717757747.247} -{"unit": "pv319_q", "value": 0.122, "time": 1717757747.247} -{"unit": "pv330_p", "value": 15.101, "time": 1717757747.539} -{"unit": "pv330_q", "value": -0.184, "time": 1717757747.539} -{"unit": "battery_p", "value": -0.223, "time": 1717757747.467} -{"unit": "battery_q", "value": 0.038, "time": 1717757747.467} -{"unit": "b2b_p", "value": -29.011, "time": 1717757747.173} -{"unit": "b2b_q", "value": 6.791, "time": 1717757747.173} -{"unit": "gaia_p", "value": 3.683, "time": 1717757747.524} -{"unit": "gaia_q", "value": -7.944, "time": 1717757747.524} -{"unit": "pcc_p", "value": -0.139, "time": 1717757748.567} -{"unit": "pcc_q", "value": 0.917, "time": 1717757748.567} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757748.621} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757748.621} -{"unit": "pv319_p", "value": 10.327, "time": 1717757748.381} -{"unit": "pv319_q", "value": 0.115, "time": 1717757748.381} -{"unit": "pv330_p", "value": 15.136, "time": 1717757748.557} -{"unit": "pv330_q", "value": -0.188, "time": 1717757748.557} -{"unit": "battery_p", "value": -0.22, "time": 1717757748.667} -{"unit": "battery_q", "value": 0.036, "time": 1717757748.667} -{"unit": "b2b_p", "value": -29.071, "time": 1717757748.501} -{"unit": "b2b_q", "value": 6.784, "time": 1717757748.772} -{"unit": "gaia_p", "value": 3.549, "time": 1717757748.67} -{"unit": "gaia_q", "value": -7.877, "time": 1717757748.67} -{"unit": "pcc_p", "value": -0.428, "time": 1717757749.652} -{"unit": "pcc_q", "value": 0.897, "time": 1717757749.652} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757749.696} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757749.696} -{"unit": "pv319_p", "value": 10.552, "time": 1717757749.77} -{"unit": "pv319_q", "value": 0.116, "time": 1717757749.77} -{"unit": "pv330_p", "value": 15.132, "time": 1717757749.776} -{"unit": "pv330_q", "value": -0.183, "time": 1717757749.776} -{"unit": "battery_p", "value": -0.22, "time": 1717757749.872} -{"unit": "battery_q", "value": 0.036, "time": 1717757749.872} -{"unit": "b2b_p", "value": -29.027, "time": 1717757749.821} -{"unit": "b2b_q", "value": 6.794, "time": 1717757749.821} -{"unit": "gaia_p", "value": 3.894, "time": 1717757749.774} -{"unit": "gaia_q", "value": -7.995, "time": 1717757749.774} -{"unit": "pcc_p", "value": -0.456, "time": 1717757750.912} -{"unit": "pcc_q", "value": 0.865, "time": 1717757750.912} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757750.956} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757750.956} -{"unit": "pv319_p", "value": 10.503, "time": 1717757750.92} -{"unit": "pv319_q", "value": 0.127, "time": 1717757750.92} -{"unit": "pv330_p", "value": 15.115, "time": 1717757750.981} -{"unit": "pv330_q", "value": -0.187, "time": 1717757750.981} -{"unit": "battery_p", "value": -0.22, "time": 1717757750.687} -{"unit": "battery_q", "value": 0.035, "time": 1717757750.687} -{"unit": "b2b_p", "value": -28.968, "time": 1717757751.015} -{"unit": "b2b_q", "value": 6.806, "time": 1717757751.015} -{"unit": "gaia_p", "value": 3.837, "time": 1717757750.9} -{"unit": "gaia_q", "value": -7.955, "time": 1717757750.9} -{"unit": "pcc_p", "value": -0.217, "time": 1717757752.017} -{"unit": "pcc_q", "value": 0.837, "time": 1717757752.017} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757752.036} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757752.036} -{"unit": "pv319_p", "value": 10.55, "time": 1717757751.842} -{"unit": "pv319_q", "value": 0.126, "time": 1717757751.842} -{"unit": "pv330_p", "value": 15.158, "time": 1717757752.136} -{"unit": "pv330_q", "value": -0.192, "time": 1717757752.136} -{"unit": "battery_p", "value": -0.22, "time": 1717757751.902} -{"unit": "battery_q", "value": 0.035, "time": 1717757751.902} -{"unit": "b2b_p", "value": -29.133, "time": 1717757752.173} -{"unit": "b2b_q", "value": 6.812, "time": 1717757752.173} -{"unit": "gaia_p", "value": 3.831, "time": 1717757752.178} -{"unit": "gaia_q", "value": -7.948, "time": 1717757752.178} -{"unit": "pcc_p", "value": -0.182, "time": 1717757753.092} -{"unit": "pcc_q", "value": 0.695, "time": 1717757753.272} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757753.156} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757753.156} -{"unit": "pv319_p", "value": 10.489, "time": 1717757753.263} -{"unit": "pv319_q", "value": 0.12, "time": 1717757753.263} -{"unit": "pv330_p", "value": 15.135, "time": 1717757753.137} -{"unit": "pv330_q", "value": -0.189, "time": 1717757753.137} -{"unit": "battery_p", "value": -0.221, "time": 1717757753.132} -{"unit": "battery_q", "value": 0.035, "time": 1717757753.132} -{"unit": "b2b_p", "value": -29.139, "time": 1717757752.499} -{"unit": "b2b_q", "value": 6.802, "time": 1717757752.499} -{"unit": "gaia_p", "value": 3.304, "time": 1717757753.298} -{"unit": "gaia_q", "value": -7.772, "time": 1717757753.298} -{"unit": "pcc_p", "value": 0.228, "time": 1717757754.352} -{"unit": "pcc_q", "value": 0.609, "time": 1717757754.352} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757754.416} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757754.416} -{"unit": "pv319_p", "value": 10.474, "time": 1717757754.351} -{"unit": "pv319_q", "value": 0.123, "time": 1717757754.351} -{"unit": "pv330_p", "value": 15.143, "time": 1717757754.391} -{"unit": "pv330_q", "value": -0.185, "time": 1717757754.391} -{"unit": "battery_p", "value": -0.223, "time": 1717757754.342} -{"unit": "battery_q", "value": 0.036, "time": 1717757754.342} -{"unit": "b2b_p", "value": -29.063, "time": 1717757753.773} -{"unit": "b2b_q", "value": 6.813, "time": 1717757753.773} -{"unit": "gaia_p", "value": 3.478, "time": 1717757754.301} -{"unit": "gaia_q", "value": -7.815, "time": 1717757754.301} -{"unit": "pcc_p", "value": 0.437, "time": 1717757755.437} -{"unit": "pcc_q", "value": 0.6, "time": 1717757755.437} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757755.496} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757755.496} -{"unit": "pv319_p", "value": 10.423, "time": 1717757755.525} -{"unit": "pv319_q", "value": 0.125, "time": 1717757755.525} -{"unit": "pv330_p", "value": 15.147, "time": 1717757755.471} -{"unit": "pv330_q", "value": -0.185, "time": 1717757755.471} -{"unit": "battery_p", "value": -0.221, "time": 1717757755.582} -{"unit": "battery_q", "value": 0.035, "time": 1717757755.582} -{"unit": "b2b_p", "value": -28.991, "time": 1717757755.533} -{"unit": "b2b_q", "value": 6.804, "time": 1717757755.533} -{"unit": "gaia_p", "value": 2.917, "time": 1717757755.523} -{"unit": "gaia_q", "value": -7.641, "time": 1717757755.523} -{"unit": "pcc_p", "value": 0.457, "time": 1717757756.512} -{"unit": "pcc_q", "value": 0.549, "time": 1717757756.512} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757756.571} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757756.571} -{"unit": "pv319_p", "value": 10.493, "time": 1717757756.329} -{"unit": "pv319_q", "value": 0.129, "time": 1717757756.329} -{"unit": "pv330_p", "value": 15.164, "time": 1717757756.554} -{"unit": "pv330_q", "value": -0.187, "time": 1717757756.554} -{"unit": "battery_p", "value": -0.221, "time": 1717757756.402} -{"unit": "battery_q", "value": 0.035, "time": 1717757756.402} -{"unit": "b2b_p", "value": -28.957, "time": 1717757756.62} -{"unit": "b2b_q", "value": 6.799, "time": 1717757756.62} -{"unit": "gaia_p", "value": 2.837, "time": 1717757756.65} -{"unit": "gaia_q", "value": -7.623, "time": 1717757756.65} -{"unit": "pcc_p", "value": -0.032, "time": 1717757757.773} -{"unit": "pcc_q", "value": 0.647, "time": 1717757757.773} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757757.636} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757757.636} -{"unit": "pv319_p", "value": 10.541, "time": 1717757757.517} -{"unit": "pv319_q", "value": 0.129, "time": 1717757757.517} -{"unit": "pv330_p", "value": 15.155, "time": 1717757757.74} -{"unit": "pv330_q", "value": -0.183, "time": 1717757757.74} -{"unit": "battery_p", "value": -0.222, "time": 1717757757.717} -{"unit": "battery_q", "value": 0.036, "time": 1717757757.717} -{"unit": "b2b_p", "value": -28.763, "time": 1717757757.689} -{"unit": "b2b_q", "value": 6.777, "time": 1717757757.689} -{"unit": "gaia_p", "value": 3.199, "time": 1717757757.697} -{"unit": "gaia_q", "value": -7.76, "time": 1717757757.697} -{"unit": "pcc_p", "value": 0.032, "time": 1717757758.842} -{"unit": "pcc_q", "value": 0.656, "time": 1717757758.842} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757758.881} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757758.881} -{"unit": "pv319_p", "value": 10.466, "time": 1717757758.924} -{"unit": "pv319_q", "value": 0.132, "time": 1717757758.924} -{"unit": "pv330_p", "value": 15.177, "time": 1717757758.74} -{"unit": "pv330_q", "value": -0.187, "time": 1717757758.74} -{"unit": "battery_p", "value": -0.222, "time": 1717757758.942} -{"unit": "battery_q", "value": 0.038, "time": 1717757758.942} -{"unit": "b2b_p", "value": -28.791, "time": 1717757758.883} -{"unit": "b2b_q", "value": 6.808, "time": 1717757758.883} -{"unit": "gaia_p", "value": 3.029, "time": 1717757758.779} -{"unit": "gaia_q", "value": -7.7, "time": 1717757758.779} -{"unit": "pcc_p", "value": -0.224, "time": 1717757759.917} -{"unit": "pcc_q", "value": 0.703, "time": 1717757759.917} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757759.951} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757759.951} -{"unit": "pv319_p", "value": 10.53, "time": 1717757759.927} -{"unit": "pv319_q", "value": 0.133, "time": 1717757759.927} -{"unit": "pv330_p", "value": 15.139, "time": 1717757760.046} -{"unit": "pv330_q", "value": -0.182, "time": 1717757760.046} -{"unit": "battery_p", "value": -0.219, "time": 1717757759.772} -{"unit": "battery_q", "value": 0.036, "time": 1717757759.772} -{"unit": "b2b_p", "value": -28.775, "time": 1717757760.104} -{"unit": "b2b_q", "value": 6.807, "time": 1717757760.104} -{"unit": "gaia_p", "value": 2.887, "time": 1717757759.882} -{"unit": "gaia_q", "value": -7.651, "time": 1717757759.882} -{"unit": "pcc_p", "value": 0.43, "time": 1717757761.177} -{"unit": "pcc_q", "value": 0.523, "time": 1717757761.177} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757761.191} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757761.191} -{"unit": "pv319_p", "value": 10.486, "time": 1717757761.134} -{"unit": "pv319_q", "value": 0.133, "time": 1717757761.134} -{"unit": "pv330_p", "value": 15.153, "time": 1717757761.201} -{"unit": "pv330_q", "value": -0.187, "time": 1717757761.201} -{"unit": "battery_p", "value": -0.22, "time": 1717757761.012} -{"unit": "battery_q", "value": 0.03, "time": 1717757761.012} -{"unit": "b2b_p", "value": -28.854, "time": 1717757761.291} -{"unit": "b2b_q", "value": 6.797, "time": 1717757761.291} -{"unit": "gaia_p", "value": 3.166, "time": 1717757761.117} -{"unit": "gaia_q", "value": -7.723, "time": 1717757761.117} -{"unit": "pcc_p", "value": 0.226, "time": 1717757762.252} -{"unit": "pcc_q", "value": 0.503, "time": 1717757762.252} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757762.271} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757762.271} -{"unit": "pv319_p", "value": 10.497, "time": 1717757762.017} -{"unit": "pv319_q", "value": 0.13, "time": 1717757762.017} -{"unit": "pv330_p", "value": 15.204, "time": 1717757762.138} -{"unit": "pv330_q", "value": -0.184, "time": 1717757762.138} -{"unit": "battery_p", "value": -0.22, "time": 1717757762.232} -{"unit": "battery_q", "value": 0.034, "time": 1717757762.232} -{"unit": "b2b_p", "value": -28.69, "time": 1717757762.41} -{"unit": "b2b_q", "value": 6.811, "time": 1717757762.41} -{"unit": "gaia_p", "value": 3.222, "time": 1717757762.191} -{"unit": "gaia_q", "value": -7.739, "time": 1717757762.191} -{"unit": "pcc_p", "value": 0.052, "time": 1717757763.322} -{"unit": "pcc_q", "value": 0.563, "time": 1717757763.322} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757763.331} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757763.331} -{"unit": "pv319_p", "value": 10.417, "time": 1717757763.437} -{"unit": "pv319_q", "value": 0.124, "time": 1717757763.437} -{"unit": "pv330_p", "value": 15.245, "time": 1717757763.483} -{"unit": "pv330_q", "value": -0.182, "time": 1717757763.483} -{"unit": "battery_p", "value": -0.222, "time": 1717757763.472} -{"unit": "battery_q", "value": 0.03, "time": 1717757763.472} -{"unit": "b2b_p", "value": -28.616, "time": 1717757763.094} -{"unit": "b2b_q", "value": 6.815, "time": 1717757763.094} -{"unit": "gaia_p", "value": 2.978, "time": 1717757763.298} -{"unit": "gaia_q", "value": -7.657, "time": 1717757763.298} -{"unit": "pcc_p", "value": 0.042, "time": 1717757764.402} -{"unit": "pcc_q", "value": 0.537, "time": 1717757764.402} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757764.406} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757764.586} -{"unit": "pv319_p", "value": 10.432, "time": 1717757764.571} -{"unit": "pv319_q", "value": 0.119, "time": 1717757764.571} -{"unit": "pv330_p", "value": 15.317, "time": 1717757764.558} -{"unit": "pv330_q", "value": -0.186, "time": 1717757764.558} -{"unit": "battery_p", "value": -0.223, "time": 1717757764.277} -{"unit": "battery_q", "value": 0.036, "time": 1717757764.277} -{"unit": "b2b_p", "value": -28.616, "time": 1717757763.094} -{"unit": "b2b_q", "value": 6.815, "time": 1717757763.094} -{"unit": "gaia_p", "value": 2.747, "time": 1717757764.323} -{"unit": "gaia_q", "value": -7.606, "time": 1717757764.323} -{"unit": "pcc_p", "value": -0.078, "time": 1717757765.657} -{"unit": "pcc_q", "value": 0.599, "time": 1717757765.657} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757765.661} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757765.661} -{"unit": "pv319_p", "value": 10.442, "time": 1717757765.578} -{"unit": "pv319_q", "value": 0.119, "time": 1717757765.578} -{"unit": "pv330_p", "value": 15.22, "time": 1717757765.744} -{"unit": "pv330_q", "value": -0.186, "time": 1717757765.744} -{"unit": "battery_p", "value": -0.221, "time": 1717757765.502} -{"unit": "battery_q", "value": 0.037, "time": 1717757765.502} -{"unit": "b2b_p", "value": -28.487, "time": 1717757765.663} -{"unit": "b2b_q", "value": 6.808, "time": 1717757765.663} -{"unit": "gaia_p", "value": 2.959, "time": 1717757765.697} -{"unit": "gaia_q", "value": -7.668, "time": 1717757765.697} -{"unit": "pcc_p", "value": 3.881, "time": 1717757766.732} -{"unit": "pcc_q", "value": 0.654, "time": 1717757766.732} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757766.736} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757766.736} -{"unit": "pv319_p", "value": 10.454, "time": 1717757766.851} -{"unit": "pv319_q", "value": 0.115, "time": 1717757766.851} -{"unit": "pv330_p", "value": 10.116, "time": 1717757766.792} -{"unit": "pv330_q", "value": -0.144, "time": 1717757766.792} -{"unit": "battery_p", "value": -0.222, "time": 1717757766.727} -{"unit": "battery_q", "value": 0.038, "time": 1717757766.727} -{"unit": "b2b_p", "value": -27.912, "time": 1717757766.874} -{"unit": "b2b_q", "value": 6.805, "time": 1717757766.874} -{"unit": "gaia_p", "value": 3.8, "time": 1717757766.9} -{"unit": "gaia_q", "value": -7.849, "time": 1717757766.9} -{"unit": "pcc_p", "value": -1.354, "time": 1717757767.862} -{"unit": "pcc_q", "value": 0.753, "time": 1717757767.862} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757767.971} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757767.971} -{"unit": "pv319_p", "value": 10.515, "time": 1717757768.031} -{"unit": "pv319_q", "value": 0.112, "time": 1717757768.031} -{"unit": "pv330_p", "value": 15.19, "time": 1717757767.984} -{"unit": "pv330_q", "value": -0.186, "time": 1717757767.984} -{"unit": "battery_p", "value": -0.221, "time": 1717757767.972} -{"unit": "battery_q", "value": 0.038, "time": 1717757767.972} -{"unit": "b2b_p", "value": -27.906, "time": 1717757767.73} -{"unit": "b2b_q", "value": 6.791, "time": 1717757767.73} -{"unit": "gaia_p", "value": 3.449, "time": 1717757768.144} -{"unit": "gaia_q", "value": -7.836, "time": 1717757768.144} -{"unit": "pcc_p", "value": 3.839, "time": 1717757769.113} -{"unit": "pcc_q", "value": 0.423, "time": 1717757769.113} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757769.091} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757769.091} -{"unit": "pv319_p", "value": 10.535, "time": 1717757769.062} -{"unit": "pv319_q", "value": 0.116, "time": 1717757769.062} -{"unit": "pv330_p", "value": 13.098, "time": 1717757769.078} -{"unit": "pv330_q", "value": -0.171, "time": 1717757769.078} -{"unit": "battery_p", "value": -0.222, "time": 1717757769.207} -{"unit": "battery_q", "value": 0.037, "time": 1717757769.207} -{"unit": "b2b_p", "value": -27.717, "time": 1717757768.597} -{"unit": "b2b_q", "value": 6.826, "time": 1717757768.597} -{"unit": "gaia_p", "value": 2.784, "time": 1717757769.318} -{"unit": "gaia_q", "value": -7.53, "time": 1717757769.318} -{"unit": "pcc_p", "value": 0.048, "time": 1717757770.203} -{"unit": "pcc_q", "value": 0.394, "time": 1717757770.203} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757770.341} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757770.341} -{"unit": "pv319_p", "value": 10.527, "time": 1717757770.369} -{"unit": "pv319_q", "value": 0.122, "time": 1717757770.369} -{"unit": "pv330_p", "value": 15.244, "time": 1717757770.336} -{"unit": "pv330_q", "value": -0.186, "time": 1717757770.336} -{"unit": "battery_p", "value": -0.22, "time": 1717757770.437} -{"unit": "battery_q", "value": 0.035, "time": 1717757770.437} -{"unit": "b2b_p", "value": -28.074, "time": 1717757770.315} -{"unit": "b2b_q", "value": 6.822, "time": 1717757770.473} -{"unit": "gaia_p", "value": 2.283, "time": 1717757770.3} -{"unit": "gaia_q", "value": -7.468, "time": 1717757770.3} -{"unit": "pcc_p", "value": 0.902, "time": 1717757771.473} -{"unit": "pcc_q", "value": 0.098, "time": 1717757771.473} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757771.401} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757771.401} -{"unit": "pv319_p", "value": 10.566, "time": 1717757771.437} -{"unit": "pv319_q", "value": 0.131, "time": 1717757771.437} -{"unit": "pv330_p", "value": 15.232, "time": 1717757771.558} -{"unit": "pv330_q", "value": -0.176, "time": 1717757771.558} -{"unit": "battery_p", "value": -0.22, "time": 1717757771.252} -{"unit": "battery_q", "value": 0.037, "time": 1717757771.252} -{"unit": "b2b_p", "value": -27.791, "time": 1717757771.277} -{"unit": "b2b_q", "value": 6.82, "time": 1717757771.277} -{"unit": "gaia_p", "value": 1.243, "time": 1717757771.542} -{"unit": "gaia_q", "value": -7.186, "time": 1717757771.542} -{"unit": "pcc_p", "value": 0.937, "time": 1717757772.543} -{"unit": "pcc_q", "value": 0.024, "time": 1717757772.543} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757772.476} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757772.651} -{"unit": "pv319_p", "value": 10.559, "time": 1717757772.579} -{"unit": "pv319_q", "value": 0.128, "time": 1717757772.579} -{"unit": "pv330_p", "value": 15.254, "time": 1717757772.637} -{"unit": "pv330_q", "value": -0.175, "time": 1717757772.637} -{"unit": "battery_p", "value": -0.222, "time": 1717757772.503} -{"unit": "battery_q", "value": 0.036, "time": 1717757772.503} -{"unit": "b2b_p", "value": -27.358, "time": 1717757772.59} -{"unit": "b2b_q", "value": 6.828, "time": 1717757772.59} -{"unit": "gaia_p", "value": 0.806, "time": 1717757772.698} -{"unit": "gaia_q", "value": -7.117, "time": 1717757772.698} -{"unit": "pcc_p", "value": 0.318, "time": 1717757773.613} -{"unit": "pcc_q", "value": 0.041, "time": 1717757773.613} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757773.716} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757773.716} -{"unit": "pv319_p", "value": 10.562, "time": 1717757773.779} -{"unit": "pv319_q", "value": 0.143, "time": 1717757773.779} -{"unit": "pv330_p", "value": 15.267, "time": 1717757773.738} -{"unit": "pv330_q", "value": -0.173, "time": 1717757773.738} -{"unit": "battery_p", "value": -0.221, "time": 1717757773.792} -{"unit": "battery_q", "value": 0.037, "time": 1717757773.792} -{"unit": "b2b_p", "value": -27.345, "time": 1717757772.789} -{"unit": "b2b_q", "value": 6.807, "time": 1717757772.789} -{"unit": "gaia_p", "value": 0.793, "time": 1717757773.779} -{"unit": "gaia_q", "value": -7.109, "time": 1717757773.779} -{"unit": "pcc_p", "value": 0.448, "time": 1717757774.858} -{"unit": "pcc_q", "value": -0.064, "time": 1717757774.858} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757774.786} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757774.786} -{"unit": "pv319_p", "value": 10.553, "time": 1717757774.785} -{"unit": "pv319_q", "value": 0.149, "time": 1717757774.785} -{"unit": "pv330_p", "value": 15.249, "time": 1717757774.79} -{"unit": "pv330_q", "value": -0.18, "time": 1717757774.79} -{"unit": "battery_p", "value": -0.219, "time": 1717757774.607} -{"unit": "battery_q", "value": 0.036, "time": 1717757774.607} -{"unit": "b2b_p", "value": -26.726, "time": 1717757774.868} -{"unit": "b2b_q", "value": 6.841, "time": 1717757774.868} -{"unit": "gaia_p", "value": 0.62, "time": 1717757774.941} -{"unit": "gaia_q", "value": -7.047, "time": 1717757774.941} -{"unit": "pcc_p", "value": 0.03, "time": 1717757775.948} -{"unit": "pcc_q", "value": 0.063, "time": 1717757775.948} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757775.876} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757775.876} -{"unit": "pv319_p", "value": 10.607, "time": 1717757775.988} -{"unit": "pv319_q", "value": 0.147, "time": 1717757775.988} -{"unit": "pv330_p", "value": 15.246, "time": 1717757775.977} -{"unit": "pv330_q", "value": -0.173, "time": 1717757775.977} -{"unit": "battery_p", "value": -0.221, "time": 1717757775.827} -{"unit": "battery_q", "value": 0.037, "time": 1717757775.827} -{"unit": "b2b_p", "value": -26.684, "time": 1717757775.925} -{"unit": "b2b_q", "value": 6.821, "time": 1717757776.063} -{"unit": "gaia_p", "value": 0.913, "time": 1717757775.916} -{"unit": "gaia_q", "value": -7.124, "time": 1717757775.916} -{"unit": "pcc_p", "value": -1.463, "time": 1717757777.029} -{"unit": "pcc_q", "value": 0.436, "time": 1717757777.029} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757776.956} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757776.956} -{"unit": "pv319_p", "value": 10.647, "time": 1717757777.129} -{"unit": "pv319_q", "value": 0.149, "time": 1717757777.129} -{"unit": "pv330_p", "value": 15.217, "time": 1717757777.055} -{"unit": "pv330_q", "value": -0.19, "time": 1717757777.055} -{"unit": "battery_p", "value": -0.221, "time": 1717757777.062} -{"unit": "battery_q", "value": 0.035, "time": 1717757777.062} -{"unit": "b2b_p", "value": -26.749, "time": 1717757777.064} -{"unit": "b2b_q", "value": 6.823, "time": 1717757777.064} -{"unit": "gaia_p", "value": 2.432, "time": 1717757777.099} -{"unit": "gaia_q", "value": -7.535, "time": 1717757777.099} -{"unit": "pcc_p", "value": -1.827, "time": 1717757778.133} -{"unit": "pcc_q", "value": 0.762, "time": 1717757778.133} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757778.201} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757778.201} -{"unit": "pv319_p", "value": 10.653, "time": 1717757778.125} -{"unit": "pv319_q", "value": 0.143, "time": 1717757778.125} -{"unit": "pv330_p", "value": 15.219, "time": 1717757778.229} -{"unit": "pv330_q", "value": -0.186, "time": 1717757778.229} -{"unit": "battery_p", "value": -0.222, "time": 1717757777.887} -{"unit": "battery_q", "value": 0.035, "time": 1717757778.287} -{"unit": "b2b_p", "value": -27.536, "time": 1717757778.263} -{"unit": "b2b_q", "value": 6.832, "time": 1717757778.263} -{"unit": "gaia_p", "value": 3.337, "time": 1717757778.186} -{"unit": "gaia_q", "value": -7.791, "time": 1717757778.186} -{"unit": "pcc_p", "value": -1.081, "time": 1717757779.223} -{"unit": "pcc_q", "value": 0.904, "time": 1717757779.223} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757779.276} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757779.276} -{"unit": "pv319_p", "value": 10.7, "time": 1717757779.237} -{"unit": "pv319_q", "value": 0.135, "time": 1717757779.237} -{"unit": "pv330_p", "value": 15.229, "time": 1717757778.884} -{"unit": "pv330_q", "value": -0.19, "time": 1717757778.884} -{"unit": "battery_p", "value": -0.221, "time": 1717757779.102} -{"unit": "battery_q", "value": 0.034, "time": 1717757779.102} -{"unit": "b2b_p", "value": -29.034, "time": 1717757779.275} -{"unit": "b2b_q", "value": 6.845, "time": 1717757779.275} -{"unit": "gaia_p", "value": 4.154, "time": 1717757779.19} -{"unit": "gaia_q", "value": -8.051, "time": 1717757779.19} -{"unit": "pcc_p", "value": -0.456, "time": 1717757780.288} -{"unit": "pcc_q", "value": 1.066, "time": 1717757780.288} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757780.351} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757780.351} -{"unit": "pv319_p", "value": 10.611, "time": 1717757780.371} -{"unit": "pv319_q", "value": 0.128, "time": 1717757780.371} -{"unit": "pv330_p", "value": 15.212, "time": 1717757780.36} -{"unit": "pv330_q", "value": -0.181, "time": 1717757780.36} -{"unit": "battery_p", "value": -0.221, "time": 1717757780.312} -{"unit": "battery_q", "value": 0.038, "time": 1717757780.312} -{"unit": "b2b_p", "value": -30.137, "time": 1717757780.422} -{"unit": "b2b_q", "value": 6.789, "time": 1717757780.422} -{"unit": "gaia_p", "value": 4.836, "time": 1717757780.45} -{"unit": "gaia_q", "value": -8.277, "time": 1717757780.45} -{"unit": "pcc_p", "value": -0.539, "time": 1717757781.538} -{"unit": "pcc_q", "value": 1.36, "time": 1717757781.538} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757781.591} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757781.591} -{"unit": "pv319_p", "value": 10.716, "time": 1717757781.526} -{"unit": "pv319_q", "value": 0.134, "time": 1717757781.526} -{"unit": "pv330_p", "value": 15.235, "time": 1717757781.384} -{"unit": "pv330_q", "value": -0.193, "time": 1717757781.384} -{"unit": "battery_p", "value": -0.221, "time": 1717757781.537} -{"unit": "battery_q", "value": 0.036, "time": 1717757781.537} -{"unit": "b2b_p", "value": -30.598, "time": 1717757781.636} -{"unit": "b2b_q", "value": 6.793, "time": 1717757781.636} -{"unit": "gaia_p", "value": 5.25, "time": 1717757781.586} -{"unit": "gaia_q", "value": -8.45, "time": 1717757781.586} -{"unit": "pcc_p", "value": -0.074, "time": 1717757782.623} -{"unit": "pcc_q", "value": 1.685, "time": 1717757782.623} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757782.665} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757782.665} -{"unit": "pv319_p", "value": 9.933, "time": 1717757782.642} -{"unit": "pv319_q", "value": 0.115, "time": 1717757782.642} -{"unit": "pv330_p", "value": 15.212, "time": 1717757782.603} -{"unit": "pv330_q", "value": -0.189, "time": 1717757782.603} -{"unit": "battery_p", "value": -0.222, "time": 1717757782.752} -{"unit": "battery_q", "value": 0.036, "time": 1717757782.752} -{"unit": "b2b_p", "value": -30.794, "time": 1717757782.705} -{"unit": "b2b_q", "value": 6.824, "time": 1717757782.705} -{"unit": "gaia_p", "value": 5.904, "time": 1717757782.699} -{"unit": "gaia_q", "value": -8.696, "time": 1717757782.699} -{"unit": "pcc_p", "value": 0.842, "time": 1717757783.793} -{"unit": "pcc_q", "value": 1.989, "time": 1717757783.793} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757783.746} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757783.746} -{"unit": "pv319_p", "value": 8.072, "time": 1717757783.725} -{"unit": "pv319_q", "value": 0.088, "time": 1717757783.725} -{"unit": "pv330_p", "value": 15.238, "time": 1717757783.473} -{"unit": "pv330_q", "value": -0.192, "time": 1717757783.473} -{"unit": "battery_p", "value": -0.221, "time": 1717757783.567} -{"unit": "battery_q", "value": 0.035, "time": 1717757783.567} -{"unit": "b2b_p", "value": -30.878, "time": 1717757783.692} -{"unit": "b2b_q", "value": 6.785, "time": 1717757783.692} -{"unit": "gaia_p", "value": 6.916, "time": 1717757783.915} -{"unit": "gaia_q", "value": -9.112, "time": 1717757783.915} -{"unit": "pcc_p", "value": 0.953, "time": 1717757784.873} -{"unit": "pcc_q", "value": 2.061, "time": 1717757784.873} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757784.816} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757784.816} -{"unit": "pv319_p", "value": 7.08, "time": 1717757784.864} -{"unit": "pv319_q", "value": 0.081, "time": 1717757784.864} -{"unit": "pv330_p", "value": 15.238, "time": 1717757783.473} -{"unit": "pv330_q", "value": -0.192, "time": 1717757783.473} -{"unit": "battery_p", "value": -0.22, "time": 1717757784.797} -{"unit": "battery_q", "value": 0.035, "time": 1717757784.797} -{"unit": "b2b_p", "value": -30.174, "time": 1717757785.023} -{"unit": "b2b_q", "value": 6.802, "time": 1717757785.023} -{"unit": "gaia_p", "value": 6.612, "time": 1717757784.69} -{"unit": "gaia_q", "value": -8.987, "time": 1717757784.69} -{"unit": "pcc_p", "value": 1.077, "time": 1717757785.963} -{"unit": "pcc_q", "value": 1.839, "time": 1717757785.963} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757785.966} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757785.966} -{"unit": "pv319_p", "value": 6.867, "time": 1717757785.985} -{"unit": "pv319_q", "value": 0.081, "time": 1717757785.985} -{"unit": "pv330_p", "value": 15.259, "time": 1717757786.033} -{"unit": "pv330_q", "value": -0.178, "time": 1717757786.033} -{"unit": "battery_p", "value": -0.221, "time": 1717757786.002} -{"unit": "battery_q", "value": 0.035, "time": 1717757786.002} -{"unit": "b2b_p", "value": -29.624, "time": 1717757786.132} -{"unit": "b2b_q", "value": 6.782, "time": 1717757786.132} -{"unit": "gaia_p", "value": 6.508, "time": 1717757786.052} -{"unit": "gaia_q", "value": -8.951, "time": 1717757786.052} -{"unit": "pcc_p", "value": 2.245, "time": 1717757787.053} -{"unit": "pcc_q", "value": 1.396, "time": 1717757787.053} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757787.211} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757787.211} -{"unit": "pv319_p", "value": 6.317, "time": 1717757786.953} -{"unit": "pv319_q", "value": 0.075, "time": 1717757786.953} -{"unit": "pv330_p", "value": 15.285, "time": 1717757787.089} -{"unit": "pv330_q", "value": -0.194, "time": 1717757787.089} -{"unit": "battery_p", "value": -0.221, "time": 1717757787.222} -{"unit": "battery_q", "value": 0.033, "time": 1717757787.222} -{"unit": "b2b_p", "value": -28.707, "time": 1717757787.284} -{"unit": "b2b_q", "value": 6.804, "time": 1717757787.284} -{"unit": "gaia_p", "value": 5.378, "time": 1717757787.099} -{"unit": "gaia_q", "value": -8.455, "time": 1717757787.099} -{"unit": "pcc_p", "value": 22.686, "time": 1717757788.298} -{"unit": "pcc_q", "value": 1.084, "time": 1717757788.298} -{"unit": "dumpload_p", "value": -20.674, "time": 1717757788.287} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757788.287} -{"unit": "pv319_p", "value": 4.618, "time": 1717757788.379} -{"unit": "pv319_q", "value": 0.047, "time": 1717757788.379} -{"unit": "pv330_p", "value": 15.297, "time": 1717757788.308} -{"unit": "pv330_q", "value": -0.193, "time": 1717757788.308} -{"unit": "battery_p", "value": -0.222, "time": 1717757788.037} -{"unit": "battery_q", "value": 0.034, "time": 1717757788.037} -{"unit": "b2b_p", "value": -27.242, "time": 1717757788.378} -{"unit": "b2b_q", "value": 6.897, "time": 1717757788.378} -{"unit": "gaia_p", "value": 5.411, "time": 1717757788.299} -{"unit": "gaia_q", "value": -8.211, "time": 1717757788.299} -{"unit": "pcc_p", "value": 10.693, "time": 1717757789.373} -{"unit": "pcc_q", "value": 1.252, "time": 1717757789.373} -{"unit": "dumpload_p", "value": -20.876, "time": 1717757789.38} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757789.38} -{"unit": "pv319_p", "value": 4.725, "time": 1717757789.422} -{"unit": "pv319_q", "value": 0.05, "time": 1717757789.422} -{"unit": "pv330_p", "value": 15.385, "time": 1717757789.304} -{"unit": "pv330_q", "value": -0.197, "time": 1717757789.304} -{"unit": "battery_p", "value": -0.22, "time": 1717757789.317} -{"unit": "battery_q", "value": 0.036, "time": 1717757789.317} -{"unit": "b2b_p", "value": -15.546, "time": 1717757789.444} -{"unit": "b2b_q", "value": 6.948, "time": 1717757789.444} -{"unit": "gaia_p", "value": 5.404, "time": 1717757789.355} -{"unit": "gaia_q", "value": -8.384, "time": 1717757789.355} -{"unit": "pcc_p", "value": 4.78, "time": 1717757790.458} -{"unit": "pcc_q", "value": 1.67, "time": 1717757790.458} -{"unit": "dumpload_p", "value": -20.955, "time": 1717757790.625} -{"unit": "dumpload_q", "value": 0.117, "time": 1717757790.625} -{"unit": "pv319_p", "value": 4.254, "time": 1717757790.582} -{"unit": "pv319_q", "value": 0.045, "time": 1717757790.582} -{"unit": "pv330_p", "value": 15.453, "time": 1717757790.638} -{"unit": "pv330_q", "value": -0.198, "time": 1717757790.638} -{"unit": "battery_p", "value": -0.22, "time": 1717757790.562} -{"unit": "battery_q", "value": 0.039, "time": 1717757790.562} -{"unit": "b2b_p", "value": -10.017, "time": 1717757790.666} -{"unit": "b2b_q", "value": 6.987, "time": 1717757790.666} -{"unit": "gaia_p", "value": 5.804, "time": 1717757790.65} -{"unit": "gaia_q", "value": -8.603, "time": 1717757790.65} -{"unit": "pcc_p", "value": 3.427, "time": 1717757791.713} -{"unit": "pcc_q", "value": 1.666, "time": 1717757791.713} -{"unit": "dumpload_p", "value": -20.986, "time": 1717757791.705} -{"unit": "dumpload_q", "value": 0.122, "time": 1717757791.705} -{"unit": "pv319_p", "value": 3.245, "time": 1717757791.553} -{"unit": "pv319_q", "value": 0.028, "time": 1717757791.842} -{"unit": "pv330_p", "value": 15.355, "time": 1717757791.737} -{"unit": "pv330_q", "value": -0.201, "time": 1717757791.737} -{"unit": "battery_p", "value": -0.221, "time": 1717757791.767} -{"unit": "battery_q", "value": 0.036, "time": 1717757791.767} -{"unit": "b2b_p", "value": -7.023, "time": 1717757791.862} -{"unit": "b2b_q", "value": 6.969, "time": 1717757791.862} -{"unit": "gaia_p", "value": 6.747, "time": 1717757791.851} -{"unit": "gaia_q", "value": -9.053, "time": 1717757791.851} -{"unit": "pcc_p", "value": 3.581, "time": 1717757792.788} -{"unit": "pcc_q", "value": 0.996, "time": 1717757792.788} -{"unit": "dumpload_p", "value": -21.0, "time": 1717757792.955} -{"unit": "dumpload_q", "value": 0.118, "time": 1717757792.955} -{"unit": "pv319_p", "value": 2.768, "time": 1717757792.969} -{"unit": "pv319_q", "value": 0.026, "time": 1717757792.969} -{"unit": "pv330_p", "value": 15.406, "time": 1717757792.937} -{"unit": "pv330_q", "value": -0.196, "time": 1717757792.937} -{"unit": "battery_p", "value": -0.221, "time": 1717757792.992} -{"unit": "battery_q", "value": 0.037, "time": 1717757792.992} -{"unit": "b2b_p", "value": -5.56, "time": 1717757792.676} -{"unit": "b2b_q", "value": 7.008, "time": 1717757792.676} -{"unit": "gaia_p", "value": 4.784, "time": 1717757792.915} -{"unit": "gaia_q", "value": -8.254, "time": 1717757792.915} -{"unit": "pcc_p", "value": 1.367, "time": 1717757794.043} -{"unit": "pcc_q", "value": 0.778, "time": 1717757794.043} -{"unit": "dumpload_p", "value": -21.018, "time": 1717757794.035} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757794.035} -{"unit": "pv319_p", "value": 4.162, "time": 1717757793.979} -{"unit": "pv319_q", "value": 0.042, "time": 1717757793.979} -{"unit": "pv330_p", "value": 15.453, "time": 1717757794.036} -{"unit": "pv330_q", "value": -0.204, "time": 1717757794.036} -{"unit": "battery_p", "value": -0.222, "time": 1717757793.797} -{"unit": "battery_q", "value": 0.037, "time": 1717757793.797} -{"unit": "b2b_p", "value": -5.543, "time": 1717757793.174} -{"unit": "b2b_q", "value": 7.002, "time": 1717757793.174} -{"unit": "gaia_p", "value": 4.219, "time": 1717757793.915} -{"unit": "gaia_q", "value": -8.081, "time": 1717757793.915} -{"unit": "pcc_p", "value": -0.04, "time": 1717757795.108} -{"unit": "pcc_q", "value": 0.293, "time": 1717757795.108} -{"unit": "dumpload_p", "value": -21.039, "time": 1717757795.136} -{"unit": "dumpload_q", "value": 0.121, "time": 1717757795.136} -{"unit": "pv319_p", "value": 6.759, "time": 1717757795.171} -{"unit": "pv319_q", "value": 0.082, "time": 1717757795.171} -{"unit": "pv330_p", "value": 15.453, "time": 1717757794.934} -{"unit": "pv330_q", "value": -0.201, "time": 1717757794.934} -{"unit": "battery_p", "value": -0.221, "time": 1717757795.037} -{"unit": "battery_q", "value": 0.039, "time": 1717757795.037} -{"unit": "b2b_p", "value": -3.542, "time": 1717757795.224} -{"unit": "b2b_q", "value": 6.986, "time": 1717757795.224} -{"unit": "gaia_p", "value": 2.327, "time": 1717757795.328} -{"unit": "gaia_q", "value": -7.536, "time": 1717757795.328} -{"unit": "pcc_p", "value": -1.507, "time": 1717757796.193} -{"unit": "pcc_q", "value": 0.2, "time": 1717757796.193} -{"unit": "dumpload_p", "value": -21.062, "time": 1717757796.21} -{"unit": "dumpload_q", "value": 0.12, "time": 1717757796.21} -{"unit": "pv319_p", "value": 9.088, "time": 1717757796.327} -{"unit": "pv319_q", "value": 0.104, "time": 1717757796.327} -{"unit": "pv330_p", "value": 15.389, "time": 1717757796.408} -{"unit": "pv330_q", "value": -0.195, "time": 1717757796.408} -{"unit": "battery_p", "value": -0.221, "time": 1717757796.267} -{"unit": "battery_q", "value": 0.036, "time": 1717757796.267} -{"unit": "b2b_p", "value": -3.73, "time": 1717757796.277} -{"unit": "b2b_q", "value": 7.048, "time": 1717757796.277} -{"unit": "gaia_p", "value": 2.009, "time": 1717757796.298} -{"unit": "gaia_q", "value": -7.447, "time": 1717757796.298} -{"unit": "pcc_p", "value": -1.319, "time": 1717757797.448} -{"unit": "pcc_q", "value": 0.429, "time": 1717757797.448} -{"unit": "dumpload_p", "value": -21.046, "time": 1717757797.475} -{"unit": "dumpload_q", "value": 0.123, "time": 1717757797.475} -{"unit": "pv319_p", "value": 9.519, "time": 1717757797.437} -{"unit": "pv319_q", "value": 0.098, "time": 1717757797.437} -{"unit": "pv330_p", "value": 15.565, "time": 1717757797.558} -{"unit": "pv330_q", "value": -0.186, "time": 1717757797.558} -{"unit": "battery_p", "value": -0.22, "time": 1717757797.472} -{"unit": "battery_q", "value": 0.038, "time": 1717757797.472} -{"unit": "b2b_p", "value": -5.278, "time": 1717757797.398} -{"unit": "b2b_q", "value": 7.085, "time": 1717757797.398} -{"unit": "gaia_p", "value": 2.819, "time": 1717757797.515} -{"unit": "gaia_q", "value": -7.672, "time": 1717757797.515} -{"unit": "pcc_p", "value": -1.139, "time": 1717757798.523} -{"unit": "pcc_q", "value": 0.617, "time": 1717757798.523} -{"unit": "dumpload_p", "value": -21.037, "time": 1717757798.555} -{"unit": "dumpload_q", "value": 0.12, "time": 1717757798.555} -{"unit": "pv319_p", "value": 9.478, "time": 1717757798.579} -{"unit": "pv319_q", "value": 0.107, "time": 1717757798.579} -{"unit": "pv330_p", "value": 15.544, "time": 1717757798.657} -{"unit": "pv330_q", "value": -0.189, "time": 1717757798.657} -{"unit": "battery_p", "value": -0.221, "time": 1717757798.692} -{"unit": "battery_q", "value": 0.036, "time": 1717757798.692} -{"unit": "b2b_p", "value": -6.53, "time": 1717757798.711} -{"unit": "b2b_q", "value": 7.0, "time": 1717757798.711} -{"unit": "gaia_p", "value": 3.625, "time": 1717757798.683} -{"unit": "gaia_q", "value": -7.906, "time": 1717757798.683} -{"unit": "pcc_p", "value": -0.679, "time": 1717757799.688} -{"unit": "pcc_q", "value": 0.619, "time": 1717757799.688} -{"unit": "dumpload_p", "value": -21.043, "time": 1717757799.82} -{"unit": "dumpload_q", "value": 0.12, "time": 1717757799.82} -{"unit": "pv319_p", "value": 10.01, "time": 1717757799.78} -{"unit": "pv319_q", "value": 0.113, "time": 1717757799.78} -{"unit": "pv330_p", "value": 15.543, "time": 1717757798.937} -{"unit": "pv330_q", "value": -0.189, "time": 1717757798.937} -{"unit": "battery_p", "value": -0.223, "time": 1717757799.532} -{"unit": "battery_q", "value": 0.037, "time": 1717757799.532} -{"unit": "b2b_p", "value": -7.272, "time": 1717757799.83} -{"unit": "b2b_q", "value": 6.982, "time": 1717757799.83} -{"unit": "gaia_p", "value": 3.667, "time": 1717757799.709} -{"unit": "gaia_q", "value": -7.916, "time": 1717757799.709} -{"unit": "pcc_p", "value": -0.943, "time": 1717757800.943} -{"unit": "pcc_q", "value": 0.631, "time": 1717757800.943} -{"unit": "dumpload_p", "value": -21.04, "time": 1717757800.895} -{"unit": "dumpload_q", "value": 0.123, "time": 1717757800.895} -{"unit": "pv319_p", "value": 10.438, "time": 1717757800.851} -{"unit": "pv319_q", "value": 0.119, "time": 1717757801.018} -{"unit": "pv330_p", "value": 15.23, "time": 1717757800.943} -{"unit": "pv330_q", "value": -0.188, "time": 1717757800.943} -{"unit": "battery_p", "value": -0.222, "time": 1717757800.762} -{"unit": "battery_q", "value": 0.038, "time": 1717757800.762} -{"unit": "b2b_p", "value": -7.585, "time": 1717757801.031} -{"unit": "b2b_q", "value": 6.982, "time": 1717757801.031} -{"unit": "gaia_p", "value": 3.726, "time": 1717757800.939} -{"unit": "gaia_q", "value": -7.939, "time": 1717757800.939} -{"unit": "pcc_p", "value": -1.133, "time": 1717757802.013} -{"unit": "pcc_q", "value": 0.86, "time": 1717757802.013} -{"unit": "dumpload_p", "value": -21.03, "time": 1717757802.036} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757802.036} -{"unit": "pv319_p", "value": 10.777, "time": 1717757802.143} -{"unit": "pv319_q", "value": 0.116, "time": 1717757802.143} -{"unit": "pv330_p", "value": 15.205, "time": 1717757802.099} -{"unit": "pv330_q", "value": -0.187, "time": 1717757802.099} -{"unit": "battery_p", "value": -0.22, "time": 1717757801.997} -{"unit": "battery_q", "value": 0.038, "time": 1717757801.997} -{"unit": "b2b_p", "value": -8.204, "time": 1717757802.089} -{"unit": "b2b_q", "value": 6.976, "time": 1717757802.089} -{"unit": "gaia_p", "value": 4.427, "time": 1717757802.184} -{"unit": "gaia_q", "value": -8.182, "time": 1717757802.184} -{"unit": "pcc_p", "value": -0.822, "time": 1717757803.273} -{"unit": "pcc_q", "value": 0.852, "time": 1717757803.273} -{"unit": "dumpload_p", "value": -21.008, "time": 1717757803.295} -{"unit": "dumpload_q", "value": 0.121, "time": 1717757803.295} -{"unit": "pv319_p", "value": 10.839, "time": 1717757803.227} -{"unit": "pv319_q", "value": 0.118, "time": 1717757803.227} -{"unit": "pv330_p", "value": 15.172, "time": 1717757803.076} -{"unit": "pv330_q", "value": -0.185, "time": 1717757803.076} -{"unit": "battery_p", "value": -0.22, "time": 1717757803.237} -{"unit": "battery_q", "value": 0.039, "time": 1717757803.237} -{"unit": "b2b_p", "value": -8.825, "time": 1717757803.224} -{"unit": "b2b_q", "value": 6.989, "time": 1717757803.224} -{"unit": "gaia_p", "value": 5.044, "time": 1717757803.316} -{"unit": "gaia_q", "value": -8.389, "time": 1717757803.316} -{"unit": "pcc_p", "value": -1.081, "time": 1717757804.348} -{"unit": "pcc_q", "value": 0.815, "time": 1717757804.523} -{"unit": "dumpload_p", "value": -21.014, "time": 1717757804.365} -{"unit": "dumpload_q", "value": 0.123, "time": 1717757804.55} -{"unit": "pv319_p", "value": 10.846, "time": 1717757804.379} -{"unit": "pv319_q", "value": 0.121, "time": 1717757804.57} -{"unit": "pv330_p", "value": 15.517, "time": 1717757804.365} -{"unit": "pv330_q", "value": -0.191, "time": 1717757804.365} -{"unit": "battery_p", "value": -0.221, "time": 1717757804.452} -{"unit": "battery_q", "value": 0.036, "time": 1717757804.452} -{"unit": "b2b_p", "value": -9.236, "time": 1717757804.29} -{"unit": "b2b_q", "value": 6.964, "time": 1717757804.29} -{"unit": "gaia_p", "value": 5.33, "time": 1717757804.356} -{"unit": "gaia_q", "value": -8.507, "time": 1717757804.356} -{"unit": "pcc_p", "value": 1.88, "time": 1717757805.589} -{"unit": "pcc_q", "value": 0.661, "time": 1717757805.589} -{"unit": "dumpload_p", "value": -20.965, "time": 1717757805.605} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757805.605} -{"unit": "pv319_p", "value": 10.826, "time": 1717757805.725} -{"unit": "pv319_q", "value": 0.119, "time": 1717757805.725} -{"unit": "pv330_p", "value": 13.537, "time": 1717757805.79} -{"unit": "pv330_q", "value": -0.17, "time": 1717757805.79} -{"unit": "battery_p", "value": -0.22, "time": 1717757805.732} -{"unit": "battery_q", "value": 0.038, "time": 1717757805.732} -{"unit": "b2b_p", "value": -9.789, "time": 1717757805.752} -{"unit": "b2b_q", "value": 6.982, "time": 1717757805.752} -{"unit": "gaia_p", "value": 4.097, "time": 1717757805.777} -{"unit": "gaia_q", "value": -8.001, "time": 1717757805.777} -{"unit": "pcc_p", "value": 4.236, "time": 1717757806.853} -{"unit": "pcc_q", "value": 0.757, "time": 1717757806.853} -{"unit": "dumpload_p", "value": -20.917, "time": 1717757806.855} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757806.855} -{"unit": "pv319_p", "value": 10.801, "time": 1717757806.841} -{"unit": "pv319_q", "value": 0.12, "time": 1717757806.841} -{"unit": "pv330_p", "value": 10.979, "time": 1717757806.737} -{"unit": "pv330_q", "value": -0.146, "time": 1717757806.737} -{"unit": "battery_p", "value": -0.221, "time": 1717757806.552} -{"unit": "battery_q", "value": 0.037, "time": 1717757806.552} -{"unit": "b2b_p", "value": -9.001, "time": 1717757806.913} -{"unit": "b2b_q", "value": 6.916, "time": 1717757806.913} -{"unit": "gaia_p", "value": 4.191, "time": 1717757806.851} -{"unit": "gaia_q", "value": -7.984, "time": 1717757806.851} -{"unit": "pcc_p", "value": 3.379, "time": 1717757807.938} -{"unit": "pcc_q", "value": 0.86, "time": 1717757807.938} -{"unit": "dumpload_p", "value": -20.925, "time": 1717757807.94} -{"unit": "dumpload_q", "value": 0.117, "time": 1717757807.94} -{"unit": "pv319_p", "value": 10.772, "time": 1717757807.971} -{"unit": "pv319_q", "value": 0.123, "time": 1717757807.971} -{"unit": "pv330_p", "value": 8.698, "time": 1717757807.983} -{"unit": "pv330_q", "value": -0.122, "time": 1717757807.983} -{"unit": "battery_p", "value": -0.221, "time": 1717757807.787} -{"unit": "battery_q", "value": 0.036, "time": 1717757807.787} -{"unit": "b2b_p", "value": -7.475, "time": 1717757807.98} -{"unit": "b2b_q", "value": 6.998, "time": 1717757807.98} -{"unit": "gaia_p", "value": 4.623, "time": 1717757808.051} -{"unit": "gaia_q", "value": -8.14, "time": 1717757808.051} -{"unit": "pcc_p", "value": 0.068, "time": 1717757809.029} -{"unit": "pcc_q", "value": 0.936, "time": 1717757809.029} -{"unit": "dumpload_p", "value": -20.961, "time": 1717757809.015} -{"unit": "dumpload_q", "value": 0.121, "time": 1717757809.015} -{"unit": "pv319_p", "value": 10.764, "time": 1717757808.925} -{"unit": "pv319_q", "value": 0.129, "time": 1717757809.136} -{"unit": "pv330_p", "value": 9.459, "time": 1717757808.867} -{"unit": "pv330_q", "value": -0.133, "time": 1717757809.156} -{"unit": "battery_p", "value": -0.222, "time": 1717757809.032} -{"unit": "battery_q", "value": 0.036, "time": 1717757809.032} -{"unit": "b2b_p", "value": -4.995, "time": 1717757809.118} -{"unit": "b2b_q", "value": 6.95, "time": 1717757809.118} -{"unit": "gaia_p", "value": 4.396, "time": 1717757808.982} -{"unit": "gaia_q", "value": -8.061, "time": 1717757808.982} -{"unit": "pcc_p", "value": -2.262, "time": 1717757810.103} -{"unit": "pcc_q", "value": 1.107, "time": 1717757810.103} -{"unit": "dumpload_p", "value": -20.982, "time": 1717757810.085} -{"unit": "dumpload_q", "value": 0.118, "time": 1717757810.085} -{"unit": "pv319_p", "value": 10.744, "time": 1717757810.187} -{"unit": "pv319_q", "value": 0.134, "time": 1717757810.187} -{"unit": "pv330_p", "value": 11.643, "time": 1717757809.861} -{"unit": "pv330_q", "value": -0.15, "time": 1717757809.861} -{"unit": "battery_p", "value": -0.219, "time": 1717757810.267} -{"unit": "battery_q", "value": 0.035, "time": 1717757810.267} -{"unit": "b2b_p", "value": -5.37, "time": 1717757810.17} -{"unit": "b2b_q", "value": 7.063, "time": 1717757810.17} -{"unit": "gaia_p", "value": 5.184, "time": 1717757810.068} -{"unit": "gaia_q", "value": -8.436, "time": 1717757810.068} -{"unit": "pcc_p", "value": -2.351, "time": 1717757811.193} -{"unit": "pcc_q", "value": 1.001, "time": 1717757811.193} -{"unit": "dumpload_p", "value": -20.976, "time": 1717757811.35} -{"unit": "dumpload_q", "value": 0.121, "time": 1717757811.35} -{"unit": "pv319_p", "value": 10.735, "time": 1717757811.218} -{"unit": "pv319_q", "value": 0.135, "time": 1717757811.218} -{"unit": "pv330_p", "value": 14.444, "time": 1717757811.191} -{"unit": "pv330_q", "value": -0.168, "time": 1717757811.191} -{"unit": "battery_p", "value": -0.22, "time": 1717757811.092} -{"unit": "battery_q", "value": 0.034, "time": 1717757811.092} -{"unit": "b2b_p", "value": -7.096, "time": 1717757811.426} -{"unit": "b2b_q", "value": 7.024, "time": 1717757811.426} -{"unit": "gaia_p", "value": 4.701, "time": 1717757811.452} -{"unit": "gaia_q", "value": -8.253, "time": 1717757811.452} -{"unit": "pcc_p", "value": -1.618, "time": 1717757812.443} -{"unit": "pcc_q", "value": 1.007, "time": 1717757812.443} -{"unit": "dumpload_p", "value": -20.958, "time": 1717757812.435} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757812.435} -{"unit": "pv319_p", "value": 10.737, "time": 1717757812.151} -{"unit": "pv319_q", "value": 0.137, "time": 1717757812.151} -{"unit": "pv330_p", "value": 15.406, "time": 1717757812.476} -{"unit": "pv330_q", "value": -0.177, "time": 1717757812.476} -{"unit": "battery_p", "value": -0.22, "time": 1717757812.317} -{"unit": "battery_q", "value": 0.035, "time": 1717757812.317} -{"unit": "b2b_p", "value": -8.464, "time": 1717757812.374} -{"unit": "b2b_q", "value": 7.03, "time": 1717757812.374} -{"unit": "gaia_p", "value": 5.094, "time": 1717757812.503} -{"unit": "gaia_q", "value": -8.397, "time": 1717757812.503} -{"unit": "pcc_p", "value": -1.757, "time": 1717757813.513} -{"unit": "pcc_q", "value": 1.475, "time": 1717757813.513} -{"unit": "dumpload_p", "value": -20.954, "time": 1717757813.515} -{"unit": "dumpload_q", "value": 0.123, "time": 1717757813.515} -{"unit": "pv319_p", "value": 10.584, "time": 1717757813.62} -{"unit": "pv319_q", "value": 0.137, "time": 1717757813.62} -{"unit": "pv330_p", "value": 15.766, "time": 1717757813.537} -{"unit": "pv330_q", "value": -0.181, "time": 1717757813.537} -{"unit": "battery_p", "value": -0.222, "time": 1717757813.542} -{"unit": "battery_q", "value": 0.035, "time": 1717757813.542} -{"unit": "b2b_p", "value": -9.902, "time": 1717757813.54} -{"unit": "b2b_q", "value": 6.968, "time": 1717757813.54} -{"unit": "gaia_p", "value": 6.308, "time": 1717757813.694} -{"unit": "gaia_q", "value": -8.88, "time": 1717757813.694} -{"unit": "pcc_p", "value": -0.937, "time": 1717757814.589} -{"unit": "pcc_q", "value": 1.538, "time": 1717757814.589} -{"unit": "dumpload_p", "value": -20.934, "time": 1717757814.6} -{"unit": "dumpload_q", "value": 0.119, "time": 1717757814.6} -{"unit": "pv319_p", "value": 10.734, "time": 1717757814.591} -{"unit": "pv319_q", "value": 0.135, "time": 1717757814.591} -{"unit": "pv330_p", "value": 15.867, "time": 1717757814.653} -{"unit": "pv330_q", "value": -0.192, "time": 1717757814.653} -{"unit": "battery_p", "value": -0.22, "time": 1717757814.762} -{"unit": "battery_q", "value": 0.036, "time": 1717757814.762} -{"unit": "b2b_p", "value": -11.067, "time": 1717757814.683} -{"unit": "b2b_q", "value": 6.981, "time": 1717757814.683} -{"unit": "gaia_p", "value": 7.085, "time": 1717757814.858} -{"unit": "gaia_q", "value": -9.217, "time": 1717757814.858} -{"unit": "pcc_p", "value": -0.425, "time": 1717757815.704} -{"unit": "pcc_q", "value": 1.814, "time": 1717757815.889} -{"unit": "dumpload_p", "value": -20.915, "time": 1717757815.86} -{"unit": "dumpload_q", "value": 0.12, "time": 1717757815.86} -{"unit": "pv319_p", "value": 10.712, "time": 1717757815.897} -{"unit": "pv319_q", "value": 0.136, "time": 1717757815.897} -{"unit": "pv330_p", "value": 15.898, "time": 1717757815.159} -{"unit": "pv330_q", "value": -0.193, "time": 1717757815.159} -{"unit": "battery_p", "value": -0.221, "time": 1717757815.572} -{"unit": "battery_q", "value": 0.035, "time": 1717757815.572} -{"unit": "b2b_p", "value": -11.868, "time": 1717757815.932} -{"unit": "b2b_q", "value": 6.961, "time": 1717757815.932} -{"unit": "gaia_p", "value": 6.652, "time": 1717757815.912} -{"unit": "gaia_q", "value": -9.01, "time": 1717757815.912} -{"unit": "pcc_p", "value": 0.056, "time": 1717757816.964} -{"unit": "pcc_q", "value": 1.624, "time": 1717757816.964} -{"unit": "dumpload_p", "value": -20.878, "time": 1717757816.935} -{"unit": "dumpload_q", "value": 0.12, "time": 1717757816.935} -{"unit": "pv319_p", "value": 10.634, "time": 1717757816.754} -{"unit": "pv319_q", "value": 0.137, "time": 1717757816.754} -{"unit": "pv330_p", "value": 15.76, "time": 1717757816.986} -{"unit": "pv330_q", "value": -0.192, "time": 1717757816.986} -{"unit": "battery_p", "value": -0.219, "time": 1717757816.792} -{"unit": "battery_q", "value": 0.036, "time": 1717757816.792} -{"unit": "b2b_p", "value": -12.083, "time": 1717757816.913} -{"unit": "b2b_q", "value": 6.975, "time": 1717757816.913} -{"unit": "gaia_p", "value": 6.341, "time": 1717757817.096} -{"unit": "gaia_q", "value": -8.855, "time": 1717757817.096} -{"unit": "pcc_p", "value": -10.477, "time": 1717757818.039} -{"unit": "pcc_q", "value": 1.918, "time": 1717757818.039} -{"unit": "dumpload_p", "value": -10.486, "time": 1717757818.06} -{"unit": "dumpload_q", "value": 0.075, "time": 1717757818.06} -{"unit": "pv319_p", "value": 10.725, "time": 1717757818.17} -{"unit": "pv319_q", "value": 0.13, "time": 1717757818.17} -{"unit": "pv330_p", "value": 15.701, "time": 1717757818.118} -{"unit": "pv330_q", "value": -0.192, "time": 1717757818.118} -{"unit": "battery_p", "value": -0.22, "time": 1717757818.042} -{"unit": "battery_q", "value": 0.035, "time": 1717757818.042} -{"unit": "b2b_p", "value": -12.106, "time": 1717757817.687} -{"unit": "b2b_q", "value": 6.976, "time": 1717757817.687} -{"unit": "gaia_p", "value": 6.141, "time": 1717757817.975} -{"unit": "gaia_q", "value": -9.171, "time": 1717757818.264} -{"unit": "pcc_p", "value": -5.306, "time": 1717757819.114} -{"unit": "pcc_q", "value": 1.69, "time": 1717757819.114} -{"unit": "dumpload_p", "value": -10.079, "time": 1717757819.135} -{"unit": "dumpload_q", "value": 0.086, "time": 1717757819.31} -{"unit": "pv319_p", "value": 10.722, "time": 1717757819.326} -{"unit": "pv319_q", "value": 0.134, "time": 1717757819.326} -{"unit": "pv330_p", "value": 15.68, "time": 1717757819.344} -{"unit": "pv330_q", "value": -0.194, "time": 1717757819.344} -{"unit": "battery_p", "value": -0.223, "time": 1717757819.287} -{"unit": "battery_q", "value": 0.035, "time": 1717757819.287} -{"unit": "b2b_p", "value": -17.385, "time": 1717757819.216} -{"unit": "b2b_q", "value": 6.907, "time": 1717757819.216} -{"unit": "gaia_p", "value": 6.338, "time": 1717757819.254} -{"unit": "gaia_q", "value": -8.926, "time": 1717757819.254} -{"unit": "pcc_p", "value": -2.027, "time": 1717757820.379} -{"unit": "pcc_q", "value": 1.443, "time": 1717757820.379} -{"unit": "dumpload_p", "value": -10.054, "time": 1717757820.385} -{"unit": "dumpload_q", "value": 0.087, "time": 1717757820.385} -{"unit": "pv319_p", "value": 10.657, "time": 1717757820.428} -{"unit": "pv319_q", "value": 0.136, "time": 1717757820.428} -{"unit": "pv330_p", "value": 15.611, "time": 1717757820.462} -{"unit": "pv330_q", "value": -0.192, "time": 1717757820.462} -{"unit": "battery_p", "value": -0.221, "time": 1717757820.112} -{"unit": "battery_q", "value": 0.036, "time": 1717757820.112} -{"unit": "b2b_p", "value": -20.059, "time": 1717757820.476} -{"unit": "b2b_q", "value": 6.912, "time": 1717757820.476} -{"unit": "gaia_p", "value": 6.295, "time": 1717757820.372} -{"unit": "gaia_q", "value": -8.571, "time": 1717757820.572} -{"unit": "pcc_p", "value": -0.375, "time": 1717757821.464} -{"unit": "pcc_q", "value": 1.208, "time": 1717757821.464} -{"unit": "dumpload_p", "value": -10.041, "time": 1717757821.47} -{"unit": "dumpload_q", "value": 0.088, "time": 1717757821.47} -{"unit": "pv319_p", "value": 10.718, "time": 1717757821.554} -{"unit": "pv319_q", "value": 0.136, "time": 1717757821.554} -{"unit": "pv330_p", "value": 15.573, "time": 1717757821.542} -{"unit": "pv330_q", "value": -0.193, "time": 1717757821.542} -{"unit": "battery_p", "value": -0.222, "time": 1717757821.397} -{"unit": "battery_q", "value": 0.037, "time": 1717757821.397} -{"unit": "b2b_p", "value": -21.537, "time": 1717757821.623} -{"unit": "b2b_q", "value": 6.929, "time": 1717757821.623} -{"unit": "gaia_p", "value": 5.373, "time": 1717757821.572} -{"unit": "gaia_q", "value": -8.46, "time": 1717757821.572} -{"unit": "pcc_p", "value": 0.294, "time": 1717757822.549} -{"unit": "pcc_q", "value": 1.203, "time": 1717757822.729} -{"unit": "dumpload_p", "value": -10.037, "time": 1717757822.72} -{"unit": "dumpload_q", "value": 0.088, "time": 1717757822.72} -{"unit": "pv319_p", "value": 10.719, "time": 1717757822.615} -{"unit": "pv319_q", "value": 0.137, "time": 1717757822.615} -{"unit": "pv330_p", "value": 15.537, "time": 1717757822.565} -{"unit": "pv330_q", "value": -0.192, "time": 1717757822.565} -{"unit": "battery_p", "value": -0.221, "time": 1717757822.632} -{"unit": "battery_q", "value": 0.039, "time": 1717757822.632} -{"unit": "b2b_p", "value": -21.729, "time": 1717757822.679} -{"unit": "b2b_q", "value": 6.913, "time": 1717757822.679} -{"unit": "gaia_p", "value": 5.055, "time": 1717757822.654} -{"unit": "gaia_q", "value": -8.33, "time": 1717757822.654} -{"unit": "pcc_p", "value": 0.656, "time": 1717757823.799} -{"unit": "pcc_q", "value": 1.181, "time": 1717757823.799} -{"unit": "dumpload_p", "value": -10.035, "time": 1717757823.795} -{"unit": "dumpload_q", "value": 0.088, "time": 1717757823.795} -{"unit": "pv319_p", "value": 10.707, "time": 1717757823.773} -{"unit": "pv319_q", "value": 0.136, "time": 1717757823.773} -{"unit": "pv330_p", "value": 15.502, "time": 1717757823.901} -{"unit": "pv330_q", "value": -0.189, "time": 1717757823.901} -{"unit": "battery_p", "value": -0.221, "time": 1717757823.862} -{"unit": "battery_q", "value": 0.038, "time": 1717757823.862} -{"unit": "b2b_p", "value": -21.729, "time": 1717757822.679} -{"unit": "b2b_q", "value": 6.913, "time": 1717757822.679} -{"unit": "gaia_p", "value": 5.194, "time": 1717757823.9} -{"unit": "gaia_q", "value": -8.399, "time": 1717757823.9} -{"unit": "pcc_p", "value": 0.162, "time": 1717757824.884} -{"unit": "pcc_q", "value": 1.424, "time": 1717757824.884} -{"unit": "dumpload_p", "value": -10.038, "time": 1717757824.87} -{"unit": "dumpload_q", "value": 0.087, "time": 1717757824.87} -{"unit": "pv319_p", "value": 10.563, "time": 1717757824.926} -{"unit": "pv319_q", "value": 0.143, "time": 1717757824.926} -{"unit": "pv330_p", "value": 15.513, "time": 1717757824.452} -{"unit": "pv330_q", "value": -0.19, "time": 1717757824.452} -{"unit": "battery_p", "value": -0.221, "time": 1717757824.667} -{"unit": "battery_q", "value": 0.037, "time": 1717757824.667} -{"unit": "b2b_p", "value": -22.143, "time": 1717757824.915} -{"unit": "b2b_q", "value": 6.89, "time": 1717757824.915} -{"unit": "gaia_p", "value": 5.882, "time": 1717757825.003} -{"unit": "gaia_q", "value": -8.664, "time": 1717757825.003} -{"unit": "pcc_p", "value": 0.007, "time": 1717757825.944} -{"unit": "pcc_q", "value": 1.862, "time": 1717757826.124} -{"unit": "dumpload_p", "value": -10.038, "time": 1717757826.135} -{"unit": "dumpload_q", "value": 0.087, "time": 1717757826.135} -{"unit": "pv319_p", "value": 10.637, "time": 1717757825.979} -{"unit": "pv319_q", "value": 0.141, "time": 1717757826.17} -{"unit": "pv330_p", "value": 15.518, "time": 1717757826.078} -{"unit": "pv330_q", "value": -0.189, "time": 1717757826.184} -{"unit": "battery_p", "value": -0.22, "time": 1717757825.907} -{"unit": "battery_q", "value": 0.036, "time": 1717757825.907} -{"unit": "b2b_p", "value": -22.344, "time": 1717757826.103} -{"unit": "b2b_q", "value": 6.893, "time": 1717757826.103} -{"unit": "gaia_p", "value": 6.904, "time": 1717757826.052} -{"unit": "gaia_q", "value": -8.956, "time": 1717757826.253} -{"unit": "pcc_p", "value": -0.239, "time": 1717757827.199} -{"unit": "pcc_q", "value": 1.828, "time": 1717757827.199} -{"unit": "dumpload_p", "value": -10.028, "time": 1717757827.21} -{"unit": "dumpload_q", "value": 0.085, "time": 1717757827.21} -{"unit": "pv319_p", "value": 10.697, "time": 1717757827.155} -{"unit": "pv319_q", "value": 0.146, "time": 1717757827.155} -{"unit": "pv330_p", "value": 15.521, "time": 1717757827.302} -{"unit": "pv330_q", "value": -0.191, "time": 1717757827.302} -{"unit": "battery_p", "value": -0.22, "time": 1717757827.132} -{"unit": "battery_q", "value": 0.037, "time": 1717757827.132} -{"unit": "b2b_p", "value": -22.794, "time": 1717757827.114} -{"unit": "b2b_q", "value": 6.882, "time": 1717757827.114} -{"unit": "gaia_p", "value": 6.97, "time": 1717757827.3} -{"unit": "gaia_q", "value": -9.13, "time": 1717757827.3} -{"unit": "pcc_p", "value": 0.263, "time": 1717757828.279} -{"unit": "pcc_q", "value": 1.951, "time": 1717757828.279} -{"unit": "dumpload_p", "value": -10.022, "time": 1717757828.275} -{"unit": "dumpload_q", "value": 0.083, "time": 1717757828.275} -{"unit": "pv319_p", "value": 10.716, "time": 1717757828.332} -{"unit": "pv319_q", "value": 0.151, "time": 1717757828.332} -{"unit": "pv330_p", "value": 15.51, "time": 1717757828.446} -{"unit": "pv330_q", "value": -0.19, "time": 1717757828.446} -{"unit": "battery_p", "value": -0.221, "time": 1717757828.342} -{"unit": "battery_q", "value": 0.029, "time": 1717757828.342} -{"unit": "b2b_p", "value": -23.402, "time": 1717757828.338} -{"unit": "b2b_q", "value": 6.913, "time": 1717757828.338} -{"unit": "gaia_p", "value": 7.045, "time": 1717757828.454} -{"unit": "gaia_q", "value": -9.146, "time": 1717757828.454} -{"unit": "pcc_p", "value": 1.049, "time": 1717757829.519} -{"unit": "pcc_q", "value": 1.445, "time": 1717757829.519} -{"unit": "dumpload_p", "value": -10.011, "time": 1717757829.52} -{"unit": "dumpload_q", "value": 0.085, "time": 1717757829.52} -{"unit": "pv319_p", "value": 10.605, "time": 1717757829.422} -{"unit": "pv319_q", "value": 0.144, "time": 1717757829.422} -{"unit": "pv330_p", "value": 15.538, "time": 1717757828.967} -{"unit": "pv330_q", "value": -0.19, "time": 1717757828.967} -{"unit": "battery_p", "value": -0.221, "time": 1717757829.557} -{"unit": "battery_q", "value": 0.037, "time": 1717757829.557} -{"unit": "b2b_p", "value": -23.148, "time": 1717757829.568} -{"unit": "b2b_q", "value": 6.874, "time": 1717757829.568} -{"unit": "gaia_p", "value": 6.263, "time": 1717757829.253} -{"unit": "gaia_q", "value": -8.796, "time": 1717757829.253} -{"unit": "pcc_p", "value": 0.819, "time": 1717757830.619} -{"unit": "pcc_q", "value": 1.25, "time": 1717757830.619} -{"unit": "dumpload_p", "value": -10.01, "time": 1717757830.58} -{"unit": "dumpload_q", "value": 0.088, "time": 1717757830.58} -{"unit": "pv319_p", "value": 10.63, "time": 1717757830.526} -{"unit": "pv319_q", "value": 0.137, "time": 1717757830.526} -{"unit": "pv330_p", "value": 15.521, "time": 1717757830.418} -{"unit": "pv330_q", "value": -0.186, "time": 1717757830.418} -{"unit": "battery_p", "value": -0.221, "time": 1717757830.377} -{"unit": "battery_q", "value": 0.037, "time": 1717757830.377} -{"unit": "b2b_p", "value": -22.491, "time": 1717757830.686} -{"unit": "b2b_q", "value": 6.887, "time": 1717757830.686} -{"unit": "gaia_p", "value": 5.773, "time": 1717757830.776} -{"unit": "gaia_q", "value": -8.584, "time": 1717757830.776} -{"unit": "pcc_p", "value": -0.195, "time": 1717757831.729} -{"unit": "pcc_q", "value": 1.686, "time": 1717757831.729} -{"unit": "dumpload_p", "value": -10.009, "time": 1717757831.66} -{"unit": "dumpload_q", "value": 0.088, "time": 1717757831.66} -{"unit": "pv319_p", "value": 10.718, "time": 1717757831.673} -{"unit": "pv319_q", "value": 0.143, "time": 1717757831.673} -{"unit": "pv330_p", "value": 15.522, "time": 1717757831.591} -{"unit": "pv330_q", "value": -0.19, "time": 1717757831.591} -{"unit": "battery_p", "value": -0.22, "time": 1717757831.612} -{"unit": "battery_q", "value": 0.037, "time": 1717757831.612} -{"unit": "b2b_p", "value": -22.493, "time": 1717757831.666} -{"unit": "b2b_q", "value": 6.902, "time": 1717757831.666} -{"unit": "gaia_p", "value": 6.944, "time": 1717757831.852} -{"unit": "gaia_q", "value": -9.107, "time": 1717757831.852} -{"unit": "pcc_p", "value": 1.046, "time": 1717757832.799} -{"unit": "pcc_q", "value": 1.262, "time": 1717757832.799} -{"unit": "dumpload_p", "value": -10.003, "time": 1717757832.91} -{"unit": "dumpload_q", "value": 0.089, "time": 1717757832.91} -{"unit": "pv319_p", "value": 10.675, "time": 1717757832.802} -{"unit": "pv319_q", "value": 0.132, "time": 1717757832.802} -{"unit": "pv330_p", "value": 15.539, "time": 1717757832.831} -{"unit": "pv330_q", "value": -0.193, "time": 1717757832.831} -{"unit": "battery_p", "value": -0.221, "time": 1717757832.822} -{"unit": "battery_q", "value": 0.035, "time": 1717757832.822} -{"unit": "b2b_p", "value": -22.763, "time": 1717757832.391} -{"unit": "b2b_q", "value": 6.92, "time": 1717757832.391} -{"unit": "gaia_p", "value": 5.666, "time": 1717757833.0} -{"unit": "gaia_q", "value": -8.545, "time": 1717757833.0} -{"unit": "pcc_p", "value": 1.408, "time": 1717757833.874} -{"unit": "pcc_q", "value": 0.937, "time": 1717757833.874} -{"unit": "dumpload_p", "value": -10.001, "time": 1717757834.05} -{"unit": "dumpload_q", "value": 0.089, "time": 1717757834.05} -{"unit": "pv319_p", "value": 10.747, "time": 1717757833.962} -{"unit": "pv319_q", "value": 0.147, "time": 1717757833.962} -{"unit": "pv330_p", "value": 15.532, "time": 1717757833.939} -{"unit": "pv330_q", "value": -0.189, "time": 1717757833.939} -{"unit": "battery_p", "value": -0.219, "time": 1717757834.037} -{"unit": "battery_q", "value": 0.033, "time": 1717757834.037} -{"unit": "b2b_p", "value": -22.431, "time": 1717757834.024} -{"unit": "b2b_q", "value": 6.856, "time": 1717757834.024} -{"unit": "gaia_p", "value": 4.75, "time": 1717757833.993} -{"unit": "gaia_q", "value": -8.177, "time": 1717757833.993} -{"unit": "pcc_p", "value": 0.081, "time": 1717757835.134} -{"unit": "pcc_q", "value": 1.212, "time": 1717757835.134} -{"unit": "dumpload_p", "value": -9.999, "time": 1717757835.12} -{"unit": "dumpload_q", "value": 0.085, "time": 1717757835.12} -{"unit": "pv319_p", "value": 10.759, "time": 1717757835.265} -{"unit": "pv319_q", "value": 0.145, "time": 1717757835.265} -{"unit": "pv330_p", "value": 15.537, "time": 1717757834.876} -{"unit": "pv330_q", "value": -0.195, "time": 1717757834.876} -{"unit": "battery_p", "value": -0.219, "time": 1717757835.252} -{"unit": "battery_q", "value": 0.031, "time": 1717757835.252} -{"unit": "b2b_p", "value": -21.713, "time": 1717757835.17} -{"unit": "b2b_q", "value": 6.883, "time": 1717757835.368} -{"unit": "gaia_p", "value": 5.495, "time": 1717757835.3} -{"unit": "gaia_q", "value": -8.494, "time": 1717757835.3} -{"unit": "pcc_p", "value": 1.196, "time": 1717757836.394} -{"unit": "pcc_q", "value": 0.625, "time": 1717757836.394} -{"unit": "dumpload_p", "value": -9.997, "time": 1717757836.385} -{"unit": "dumpload_q", "value": 0.085, "time": 1717757836.385} -{"unit": "pv319_p", "value": 10.742, "time": 1717757836.26} -{"unit": "pv319_q", "value": 0.136, "time": 1717757836.26} -{"unit": "pv330_p", "value": 15.551, "time": 1717757835.403} -{"unit": "pv330_q", "value": -0.194, "time": 1717757835.403} -{"unit": "battery_p", "value": -0.221, "time": 1717757836.472} -{"unit": "battery_q", "value": 0.035, "time": 1717757836.472} -{"unit": "b2b_p", "value": -20.949, "time": 1717757836.432} -{"unit": "b2b_q", "value": 6.86, "time": 1717757836.432} -{"unit": "gaia_p", "value": 3.547, "time": 1717757836.453} -{"unit": "gaia_q", "value": -7.781, "time": 1717757836.453} -{"unit": "pcc_p", "value": 1.934, "time": 1717757837.474} -{"unit": "pcc_q", "value": 0.267, "time": 1717757837.474} -{"unit": "dumpload_p", "value": -9.99, "time": 1717757837.47} -{"unit": "dumpload_q", "value": 0.085, "time": 1717757837.47} -{"unit": "pv319_p", "value": 10.679, "time": 1717757837.594} -{"unit": "pv319_q", "value": 0.128, "time": 1717757837.594} -{"unit": "pv330_p", "value": 15.531, "time": 1717757837.466} -{"unit": "pv330_q", "value": -0.19, "time": 1717757837.466} -{"unit": "battery_p", "value": -0.221, "time": 1717757837.367} -{"unit": "battery_q", "value": 0.035, "time": 1717757837.367} -{"unit": "b2b_p", "value": -20.748, "time": 1717757837.098} -{"unit": "b2b_q", "value": 6.9, "time": 1717757837.098} -{"unit": "gaia_p", "value": 2.943, "time": 1717757837.652} -{"unit": "gaia_q", "value": -7.612, "time": 1717757837.652} -{"unit": "pcc_p", "value": -0.064, "time": 1717757838.749} -{"unit": "pcc_q", "value": 0.724, "time": 1717757838.749} -{"unit": "dumpload_p", "value": -10.008, "time": 1717757838.733} -{"unit": "dumpload_q", "value": 0.089, "time": 1717757838.733} -{"unit": "pv319_p", "value": 10.653, "time": 1717757838.726} -{"unit": "pv319_q", "value": 0.125, "time": 1717757838.726} -{"unit": "pv330_p", "value": 15.568, "time": 1717757838.578} -{"unit": "pv330_q", "value": -0.193, "time": 1717757838.835} -{"unit": "battery_p", "value": -0.221, "time": 1717757838.587} -{"unit": "battery_q", "value": 0.036, "time": 1717757838.587} -{"unit": "b2b_p", "value": -19.794, "time": 1717757838.826} -{"unit": "b2b_q", "value": 6.893, "time": 1717757838.826} -{"unit": "gaia_p", "value": 2.346, "time": 1717757838.654} -{"unit": "gaia_q", "value": -7.415, "time": 1717757838.654} -{"unit": "pcc_p", "value": -1.141, "time": 1717757839.824} -{"unit": "pcc_q", "value": 1.174, "time": 1717757839.824} -{"unit": "dumpload_p", "value": -10.02, "time": 1717757839.805} -{"unit": "dumpload_q", "value": 0.087, "time": 1717757839.805} -{"unit": "pv319_p", "value": 10.704, "time": 1717757839.926} -{"unit": "pv319_q", "value": 0.124, "time": 1717757839.926} -{"unit": "pv330_p", "value": 15.592, "time": 1717757839.383} -{"unit": "pv330_q", "value": -0.191, "time": 1717757839.383} -{"unit": "battery_p", "value": -0.222, "time": 1717757839.807} -{"unit": "battery_q", "value": 0.035, "time": 1717757839.807} -{"unit": "b2b_p", "value": -20.246, "time": 1717757839.904} -{"unit": "b2b_q", "value": 6.886, "time": 1717757839.904} -{"unit": "gaia_p", "value": 3.398, "time": 1717757839.695} -{"unit": "gaia_q", "value": -7.759, "time": 1717757839.695} -{"unit": "pcc_p", "value": -0.527, "time": 1717757840.909} -{"unit": "pcc_q", "value": 1.126, "time": 1717757840.909} -{"unit": "dumpload_p", "value": -10.007, "time": 1717757840.88} -{"unit": "dumpload_q", "value": 0.086, "time": 1717757841.055} -{"unit": "pv319_p", "value": 10.736, "time": 1717757841.042} -{"unit": "pv319_q", "value": 0.137, "time": 1717757841.042} -{"unit": "pv330_p", "value": 15.558, "time": 1717757840.898} -{"unit": "pv330_q", "value": -0.193, "time": 1717757840.898} -{"unit": "battery_p", "value": -0.22, "time": 1717757841.017} -{"unit": "battery_q", "value": 0.035, "time": 1717757841.017} -{"unit": "b2b_p", "value": -20.923, "time": 1717757841.107} -{"unit": "b2b_q", "value": 6.898, "time": 1717757841.107} -{"unit": "gaia_p", "value": 5.264, "time": 1717757841.121} -{"unit": "gaia_q", "value": -8.4, "time": 1717757841.121} -{"unit": "pcc_p", "value": -0.657, "time": 1717757842.169} -{"unit": "pcc_q", "value": 1.317, "time": 1717757842.169} -{"unit": "dumpload_p", "value": -10.006, "time": 1717757842.125} -{"unit": "dumpload_q", "value": 0.087, "time": 1717757842.125} -{"unit": "pv319_p", "value": 10.708, "time": 1717757841.841} -{"unit": "pv319_q", "value": 0.136, "time": 1717757841.841} -{"unit": "pv330_p", "value": 15.584, "time": 1717757842.23} -{"unit": "pv330_q", "value": -0.193, "time": 1717757842.23} -{"unit": "battery_p", "value": -0.219, "time": 1717757842.242} -{"unit": "battery_q", "value": 0.03, "time": 1717757842.242} -{"unit": "b2b_p", "value": -21.289, "time": 1717757842.263} -{"unit": "b2b_q", "value": 6.891, "time": 1717757842.263} -{"unit": "gaia_p", "value": 5.694, "time": 1717757842.254} -{"unit": "gaia_q", "value": -8.571, "time": 1717757842.254} -{"unit": "pcc_p", "value": -0.429, "time": 1717757843.249} -{"unit": "pcc_q", "value": 1.482, "time": 1717757843.249} -{"unit": "dumpload_p", "value": -10.007, "time": 1717757843.21} -{"unit": "dumpload_q", "value": 0.087, "time": 1717757843.21} -{"unit": "pv319_p", "value": 10.563, "time": 1717757843.329} -{"unit": "pv319_q", "value": 0.141, "time": 1717757843.329} -{"unit": "pv330_p", "value": 15.597, "time": 1717757843.208} -{"unit": "pv330_q", "value": -0.193, "time": 1717757843.208} -{"unit": "battery_p", "value": -0.22, "time": 1717757843.057} -{"unit": "battery_q", "value": 0.034, "time": 1717757843.057} -{"unit": "b2b_p", "value": -21.685, "time": 1717757843.164} -{"unit": "b2b_q", "value": 6.916, "time": 1717757843.164} -{"unit": "gaia_p", "value": 6.143, "time": 1717757843.253} -{"unit": "gaia_q", "value": -8.637, "time": 1717757843.465} -{"unit": "pcc_p", "value": -0.106, "time": 1717757844.324} -{"unit": "pcc_q", "value": 1.231, "time": 1717757844.499} -{"unit": "dumpload_p", "value": -9.999, "time": 1717757844.475} -{"unit": "dumpload_q", "value": 0.089, "time": 1717757844.475} -{"unit": "pv319_p", "value": 10.674, "time": 1717757844.419} -{"unit": "pv319_q", "value": 0.146, "time": 1717757844.419} -{"unit": "pv330_p", "value": 15.579, "time": 1717757844.102} -{"unit": "pv330_q", "value": -0.19, "time": 1717757844.102} -{"unit": "battery_p", "value": -0.221, "time": 1717757844.267} -{"unit": "battery_q", "value": 0.036, "time": 1717757844.267} -{"unit": "b2b_p", "value": -21.86, "time": 1717757844.475} -{"unit": "b2b_q", "value": 6.87, "time": 1717757844.475} -{"unit": "gaia_p", "value": 5.616, "time": 1717757844.522} -{"unit": "gaia_q", "value": -8.529, "time": 1717757844.522} -{"unit": "pcc_p", "value": -0.639, "time": 1717757845.584} -{"unit": "pcc_q", "value": 1.469, "time": 1717757845.584} -{"unit": "dumpload_p", "value": -10.002, "time": 1717757845.55} -{"unit": "dumpload_q", "value": 0.083, "time": 1717757845.55} -{"unit": "pv319_p", "value": 10.735, "time": 1717757845.62} -{"unit": "pv319_q", "value": 0.151, "time": 1717757845.62} -{"unit": "pv330_p", "value": 15.645, "time": 1717757845.031} -{"unit": "pv330_q", "value": -0.194, "time": 1717757845.031} -{"unit": "battery_p", "value": -0.221, "time": 1717757845.477} -{"unit": "battery_q", "value": 0.036, "time": 1717757845.477} -{"unit": "b2b_p", "value": -21.765, "time": 1717757845.649} -{"unit": "b2b_q", "value": 6.881, "time": 1717757845.649} -{"unit": "gaia_p", "value": 6.241, "time": 1717757845.652} -{"unit": "gaia_q", "value": -8.818, "time": 1717757845.652} -{"unit": "pcc_p", "value": -0.39, "time": 1717757846.824} -{"unit": "pcc_q", "value": 1.531, "time": 1717757846.824} -{"unit": "dumpload_p", "value": -10.005, "time": 1717757846.81} -{"unit": "dumpload_q", "value": 0.085, "time": 1717757846.81} -{"unit": "pv319_p", "value": 10.819, "time": 1717757846.756} -{"unit": "pv319_q", "value": 0.141, "time": 1717757846.756} -{"unit": "pv330_p", "value": 15.74, "time": 1717757846.869} -{"unit": "pv330_q", "value": -0.197, "time": 1717757846.869} -{"unit": "battery_p", "value": -0.221, "time": 1717757846.692} -{"unit": "battery_q", "value": 0.035, "time": 1717757846.692} -{"unit": "b2b_p", "value": -22.08, "time": 1717757846.724} -{"unit": "b2b_q", "value": 6.872, "time": 1717757846.724} -{"unit": "gaia_p", "value": 5.903, "time": 1717757846.769} -{"unit": "gaia_q", "value": -8.671, "time": 1717757846.769} -{"unit": "pcc_p", "value": -8.657, "time": 1717757847.929} -{"unit": "pcc_q", "value": 1.611, "time": 1717757847.929} -{"unit": "dumpload_p", "value": -1.585, "time": 1717757847.905} -{"unit": "dumpload_q", "value": -0.009, "time": 1717757847.905} -{"unit": "pv319_p", "value": 10.832, "time": 1717757847.909} -{"unit": "pv319_q", "value": 0.132, "time": 1717757847.909} -{"unit": "pv330_p", "value": 15.615, "time": 1717757847.939} -{"unit": "pv330_q", "value": -0.197, "time": 1717757847.939} -{"unit": "battery_p", "value": -0.221, "time": 1717757847.932} -{"unit": "battery_q", "value": 0.035, "time": 1717757847.932} -{"unit": "b2b_p", "value": -22.242, "time": 1717757847.501} -{"unit": "b2b_q", "value": 6.881, "time": 1717757847.501} -{"unit": "gaia_p", "value": 5.271, "time": 1717757848.053} -{"unit": "gaia_q", "value": -8.518, "time": 1717757848.053} -{"unit": "pcc_p", "value": -5.057, "time": 1717757849.179} -{"unit": "pcc_q", "value": 0.99, "time": 1717757849.179} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757849.195} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757849.195} -{"unit": "pv319_p", "value": 10.847, "time": 1717757849.182} -{"unit": "pv319_q", "value": 0.133, "time": 1717757849.182} -{"unit": "pv330_p", "value": 15.603, "time": 1717757849.156} -{"unit": "pv330_q", "value": -0.194, "time": 1717757849.156} -{"unit": "battery_p", "value": -0.22, "time": 1717757849.162} -{"unit": "battery_q", "value": 0.033, "time": 1717757849.162} -{"unit": "b2b_p", "value": -25.186, "time": 1717757849.328} -{"unit": "b2b_q", "value": 7.134, "time": 1717757849.328} -{"unit": "gaia_p", "value": 5.458, "time": 1717757849.271} -{"unit": "gaia_q", "value": -8.588, "time": 1717757849.271} -{"unit": "pcc_p", "value": -2.564, "time": 1717757850.244} -{"unit": "pcc_q", "value": 1.226, "time": 1717757850.244} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757850.265} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757850.265} -{"unit": "pv319_p", "value": 10.708, "time": 1717757850.328} -{"unit": "pv319_q", "value": 0.133, "time": 1717757850.328} -{"unit": "pv330_p", "value": 15.631, "time": 1717757850.301} -{"unit": "pv330_q", "value": -0.192, "time": 1717757850.301} -{"unit": "battery_p", "value": -0.219, "time": 1717757850.387} -{"unit": "battery_q", "value": 0.034, "time": 1717757850.387} -{"unit": "b2b_p", "value": -29.445, "time": 1717757850.414} -{"unit": "b2b_q", "value": 6.884, "time": 1717757850.414} -{"unit": "gaia_p", "value": 5.918, "time": 1717757850.382} -{"unit": "gaia_q", "value": -8.69, "time": 1717757850.382} -{"unit": "pcc_p", "value": -1.073, "time": 1717757851.499} -{"unit": "pcc_q", "value": 1.269, "time": 1717757851.499} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757851.51} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757851.51} -{"unit": "pv319_p", "value": 10.813, "time": 1717757851.349} -{"unit": "pv319_q", "value": 0.135, "time": 1717757851.349} -{"unit": "pv330_p", "value": 15.661, "time": 1717757851.432} -{"unit": "pv330_q", "value": -0.188, "time": 1717757851.432} -{"unit": "battery_p", "value": -0.219, "time": 1717757851.207} -{"unit": "battery_q", "value": 0.03, "time": 1717757851.207} -{"unit": "b2b_p", "value": -30.618, "time": 1717757851.476} -{"unit": "b2b_q", "value": 6.852, "time": 1717757851.476} -{"unit": "gaia_p", "value": 5.339, "time": 1717757851.569} -{"unit": "gaia_q", "value": -8.393, "time": 1717757851.569} -{"unit": "pcc_p", "value": 0.049, "time": 1717757852.579} -{"unit": "pcc_q", "value": 1.065, "time": 1717757852.579} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757852.585} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757852.585} -{"unit": "pv319_p", "value": 10.79, "time": 1717757852.421} -{"unit": "pv319_q", "value": 0.133, "time": 1717757852.421} -{"unit": "pv330_p", "value": 15.66, "time": 1717757852.547} -{"unit": "pv330_q", "value": -0.187, "time": 1717757852.547} -{"unit": "battery_p", "value": -0.219, "time": 1717757852.437} -{"unit": "battery_q", "value": 0.034, "time": 1717757852.437} -{"unit": "b2b_p", "value": -31.172, "time": 1717757852.516} -{"unit": "b2b_q", "value": 6.854, "time": 1717757852.516} -{"unit": "gaia_p", "value": 4.923, "time": 1717757852.654} -{"unit": "gaia_q", "value": -8.213, "time": 1717757852.654} -{"unit": "pcc_p", "value": 0.069, "time": 1717757853.674} -{"unit": "pcc_q", "value": 1.021, "time": 1717757853.674} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757853.665} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757853.665} -{"unit": "pv319_p", "value": 10.905, "time": 1717757853.727} -{"unit": "pv319_q", "value": 0.131, "time": 1717757853.727} -{"unit": "pv330_p", "value": 15.67, "time": 1717757853.58} -{"unit": "pv330_q", "value": -0.192, "time": 1717757853.58} -{"unit": "battery_p", "value": -0.222, "time": 1717757853.762} -{"unit": "battery_q", "value": 0.034, "time": 1717757853.762} -{"unit": "b2b_p", "value": -31.297, "time": 1717757852.888} -{"unit": "b2b_q", "value": 6.794, "time": 1717757852.888} -{"unit": "gaia_p", "value": 4.735, "time": 1717757853.854} -{"unit": "gaia_q", "value": -8.155, "time": 1717757853.854} -{"unit": "pcc_p", "value": 0.198, "time": 1717757854.764} -{"unit": "pcc_q", "value": 1.045, "time": 1717757854.764} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757854.76} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757854.76} -{"unit": "pv319_p", "value": 10.88, "time": 1717757854.78} -{"unit": "pv319_q", "value": 0.127, "time": 1717757854.78} -{"unit": "pv330_p", "value": 15.684, "time": 1717757854.545} -{"unit": "pv330_q", "value": -0.198, "time": 1717757854.545} -{"unit": "battery_p", "value": -0.222, "time": 1717757854.577} -{"unit": "battery_q", "value": 0.039, "time": 1717757854.577} -{"unit": "b2b_p", "value": -31.422, "time": 1717757854.769} -{"unit": "b2b_q", "value": 6.802, "time": 1717757854.769} -{"unit": "gaia_p", "value": 4.771, "time": 1717757854.871} -{"unit": "gaia_q", "value": -8.169, "time": 1717757854.871} -{"unit": "pcc_p", "value": -0.049, "time": 1717757855.864} -{"unit": "pcc_q", "value": 1.126, "time": 1717757855.864} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757856.01} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757856.01} -{"unit": "pv319_p", "value": 10.87, "time": 1717757855.933} -{"unit": "pv319_q", "value": 0.134, "time": 1717757855.933} -{"unit": "pv330_p", "value": 15.698, "time": 1717757855.945} -{"unit": "pv330_q", "value": -0.191, "time": 1717757855.945} -{"unit": "battery_p", "value": -0.221, "time": 1717757855.802} -{"unit": "battery_q", "value": 0.036, "time": 1717757855.802} -{"unit": "b2b_p", "value": -31.301, "time": 1717757855.814} -{"unit": "b2b_q", "value": 6.806, "time": 1717757855.814} -{"unit": "gaia_p", "value": 4.898, "time": 1717757856.015} -{"unit": "gaia_q", "value": -8.238, "time": 1717757856.015} -{"unit": "pcc_p", "value": 0.245, "time": 1717757857.119} -{"unit": "pcc_q", "value": 0.947, "time": 1717757857.119} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757857.07} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757857.07} -{"unit": "pv319_p", "value": 10.86, "time": 1717757857.147} -{"unit": "pv319_q", "value": 0.132, "time": 1717757857.147} -{"unit": "pv330_p", "value": 15.701, "time": 1717757857.142} -{"unit": "pv330_q", "value": -0.19, "time": 1717757857.142} -{"unit": "battery_p", "value": -0.221, "time": 1717757857.027} -{"unit": "battery_q", "value": 0.035, "time": 1717757857.027} -{"unit": "b2b_p", "value": -31.265, "time": 1717757857.173} -{"unit": "b2b_q", "value": 6.791, "time": 1717757857.173} -{"unit": "gaia_p", "value": 4.366, "time": 1717757857.263} -{"unit": "gaia_q", "value": -8.019, "time": 1717757857.263} -{"unit": "pcc_p", "value": -0.191, "time": 1717757858.184} -{"unit": "pcc_q", "value": 1.044, "time": 1717757858.184} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757858.155} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757858.335} -{"unit": "pv319_p", "value": 10.919, "time": 1717757858.22} -{"unit": "pv319_q", "value": 0.128, "time": 1717757858.22} -{"unit": "pv330_p", "value": 15.69, "time": 1717757858.338} -{"unit": "pv330_q", "value": -0.195, "time": 1717757858.338} -{"unit": "battery_p", "value": -0.219, "time": 1717757858.247} -{"unit": "battery_q", "value": 0.036, "time": 1717757858.247} -{"unit": "b2b_p", "value": -31.155, "time": 1717757858.388} -{"unit": "b2b_q", "value": 6.8, "time": 1717757858.388} -{"unit": "gaia_p", "value": 4.981, "time": 1717757858.332} -{"unit": "gaia_q", "value": -8.244, "time": 1717757858.332} -{"unit": "pcc_p", "value": -0.643, "time": 1717757859.264} -{"unit": "pcc_q", "value": 1.318, "time": 1717757859.439} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757859.415} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757859.415} -{"unit": "pv319_p", "value": 10.93, "time": 1717757859.429} -{"unit": "pv319_q", "value": 0.13, "time": 1717757859.429} -{"unit": "pv330_p", "value": 15.707, "time": 1717757858.98} -{"unit": "pv330_q", "value": -0.192, "time": 1717757858.98} -{"unit": "battery_p", "value": -0.222, "time": 1717757859.467} -{"unit": "battery_q", "value": 0.033, "time": 1717757859.467} -{"unit": "b2b_p", "value": -31.25, "time": 1717757859.569} -{"unit": "b2b_q", "value": 6.783, "time": 1717757859.569} -{"unit": "gaia_p", "value": 5.509, "time": 1717757859.513} -{"unit": "gaia_q", "value": -8.479, "time": 1717757859.513} -{"unit": "pcc_p", "value": -0.442, "time": 1717757860.52} -{"unit": "pcc_q", "value": 1.291, "time": 1717757860.52} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757860.5} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757860.5} -{"unit": "pv319_p", "value": 10.872, "time": 1717757860.533} -{"unit": "pv319_q", "value": 0.13, "time": 1717757860.533} -{"unit": "pv330_p", "value": 15.725, "time": 1717757860.009} -{"unit": "pv330_q", "value": -0.195, "time": 1717757860.676} -{"unit": "battery_p", "value": -0.222, "time": 1717757860.277} -{"unit": "battery_q", "value": 0.035, "time": 1717757860.687} -{"unit": "b2b_p", "value": -31.572, "time": 1717757860.523} -{"unit": "b2b_q", "value": 6.797, "time": 1717757860.523} -{"unit": "gaia_p", "value": 5.614, "time": 1717757860.569} -{"unit": "gaia_q", "value": -8.478, "time": 1717757860.569} -{"unit": "pcc_p", "value": -31.072, "time": 1717757861.585} -{"unit": "pcc_q", "value": 4.989, "time": 1717757861.585} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757861.76} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757861.76} -{"unit": "pv319_p", "value": 10.9, "time": 1717757861.728} -{"unit": "pv319_q", "value": 0.133, "time": 1717757861.728} -{"unit": "pv330_p", "value": 15.774, "time": 1717757861.703} -{"unit": "pv330_q", "value": -0.196, "time": 1717757861.703} -{"unit": "battery_p", "value": -0.22, "time": 1717757861.502} -{"unit": "battery_q", "value": 0.035, "time": 1717757861.502} -{"unit": "b2b_p", "value": -1.19, "time": 1717757861.62} -{"unit": "b2b_q", "value": 3.361, "time": 1717757861.62} -{"unit": "gaia_p", "value": 5.925, "time": 1717757861.769} -{"unit": "gaia_q", "value": -9.106, "time": 1717757861.92} -{"unit": "pcc_p", "value": -30.96, "time": 1717757862.84} -{"unit": "pcc_q", "value": 5.077, "time": 1717757862.84} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757862.825} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757862.825} -{"unit": "pv319_p", "value": 10.688, "time": 1717757862.82} -{"unit": "pv319_q", "value": 0.134, "time": 1717757862.82} -{"unit": "pv330_p", "value": 15.794, "time": 1717757862.792} -{"unit": "pv330_q", "value": -0.191, "time": 1717757862.792} -{"unit": "battery_p", "value": -0.22, "time": 1717757862.717} -{"unit": "battery_q", "value": 0.035, "time": 1717757862.717} -{"unit": "b2b_p", "value": -0.909, "time": 1717757862.687} -{"unit": "b2b_q", "value": 3.519, "time": 1717757862.687} -{"unit": "gaia_p", "value": 5.141, "time": 1717757863.054} -{"unit": "gaia_q", "value": -8.757, "time": 1717757863.054} -{"unit": "pcc_p", "value": -27.822, "time": 1717757863.945} -{"unit": "pcc_q", "value": 4.876, "time": 1717757863.945} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757864.085} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757864.085} -{"unit": "pv319_p", "value": 8.072, "time": 1717757863.982} -{"unit": "pv319_q", "value": 0.091, "time": 1717757863.982} -{"unit": "pv330_p", "value": 15.805, "time": 1717757863.993} -{"unit": "pv330_q", "value": -0.191, "time": 1717757863.993} -{"unit": "battery_p", "value": -0.221, "time": 1717757863.927} -{"unit": "battery_q", "value": 0.033, "time": 1717757863.927} -{"unit": "b2b_p", "value": -0.908, "time": 1717757864.086} -{"unit": "b2b_q", "value": 3.5, "time": 1717757864.086} -{"unit": "gaia_p", "value": 4.837, "time": 1717757864.172} -{"unit": "gaia_q", "value": -8.601, "time": 1717757864.172} -{"unit": "pcc_p", "value": -26.289, "time": 1717757865.03} -{"unit": "pcc_q", "value": 4.827, "time": 1717757865.03} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757865.205} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757865.205} -{"unit": "pv319_p", "value": 6.423, "time": 1717757864.994} -{"unit": "pv319_q", "value": 0.072, "time": 1717757865.24} -{"unit": "pv330_p", "value": 15.814, "time": 1717757864.267} -{"unit": "pv330_q", "value": -0.198, "time": 1717757864.267} -{"unit": "battery_p", "value": -0.219, "time": 1717757865.147} -{"unit": "battery_q", "value": 0.035, "time": 1717757865.147} -{"unit": "b2b_p", "value": -0.907, "time": 1717757865.239} -{"unit": "b2b_q", "value": 3.499, "time": 1717757865.239} -{"unit": "gaia_p", "value": 4.763, "time": 1717757864.956} -{"unit": "gaia_q", "value": -8.314, "time": 1717757865.344} -{"unit": "pcc_p", "value": -28.487, "time": 1717757866.275} -{"unit": "pcc_q", "value": 4.621, "time": 1717757866.275} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757866.27} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757866.27} -{"unit": "pv319_p", "value": 8.812, "time": 1717757866.241} -{"unit": "pv319_q", "value": 0.103, "time": 1717757866.241} -{"unit": "pv330_p", "value": 15.856, "time": 1717757866.279} -{"unit": "pv330_q", "value": -0.199, "time": 1717757866.279} -{"unit": "battery_p", "value": -0.221, "time": 1717757866.357} -{"unit": "battery_q", "value": 0.034, "time": 1717757866.357} -{"unit": "b2b_p", "value": -0.909, "time": 1717757866.315} -{"unit": "b2b_q", "value": 3.51, "time": 1717757866.315} -{"unit": "gaia_p", "value": 4.377, "time": 1717757866.384} -{"unit": "gaia_q", "value": -8.455, "time": 1717757866.384} -{"unit": "pcc_p", "value": -29.948, "time": 1717757867.36} -{"unit": "pcc_q", "value": 4.564, "time": 1717757867.36} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757867.33} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757867.33} -{"unit": "pv319_p", "value": 10.757, "time": 1717757867.318} -{"unit": "pv319_q", "value": 0.135, "time": 1717757867.318} -{"unit": "pv330_p", "value": 15.823, "time": 1717757867.339} -{"unit": "pv330_q", "value": -0.194, "time": 1717757867.541} -{"unit": "battery_p", "value": -0.221, "time": 1717757867.172} -{"unit": "battery_q", "value": 0.035, "time": 1717757867.172} -{"unit": "b2b_p", "value": -0.91, "time": 1717757867.536} -{"unit": "b2b_q", "value": 3.527, "time": 1717757867.536} -{"unit": "gaia_p", "value": 4.095, "time": 1717757867.568} -{"unit": "gaia_q", "value": -8.392, "time": 1717757867.568} -{"unit": "pcc_p", "value": -29.915, "time": 1717757868.615} -{"unit": "pcc_q", "value": 4.497, "time": 1717757868.615} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757868.595} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757868.595} -{"unit": "pv319_p", "value": 10.984, "time": 1717757868.581} -{"unit": "pv319_q", "value": 0.134, "time": 1717757868.581} -{"unit": "pv330_p", "value": 15.868, "time": 1717757868.38} -{"unit": "pv330_q", "value": -0.2, "time": 1717757868.738} -{"unit": "battery_p", "value": -0.221, "time": 1717757868.412} -{"unit": "battery_q", "value": 0.036, "time": 1717757868.412} -{"unit": "b2b_p", "value": -0.91, "time": 1717757867.994} -{"unit": "b2b_q", "value": 3.523, "time": 1717757867.994} -{"unit": "gaia_p", "value": 3.838, "time": 1717757868.77} -{"unit": "gaia_q", "value": -8.304, "time": 1717757868.77} -{"unit": "pcc_p", "value": -29.671, "time": 1717757869.705} -{"unit": "pcc_q", "value": 4.368, "time": 1717757869.705} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757869.84} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757869.84} -{"unit": "pv319_p", "value": 11.002, "time": 1717757869.82} -{"unit": "pv319_q", "value": 0.131, "time": 1717757869.82} -{"unit": "pv330_p", "value": 15.908, "time": 1717757869.56} -{"unit": "pv330_q", "value": -0.192, "time": 1717757869.56} -{"unit": "battery_p", "value": -0.219, "time": 1717757869.677} -{"unit": "battery_q", "value": 0.036, "time": 1717757869.677} -{"unit": "b2b_p", "value": -0.908, "time": 1717757869.846} -{"unit": "b2b_q", "value": 3.505, "time": 1717757869.846} -{"unit": "gaia_p", "value": 3.549, "time": 1717757869.87} -{"unit": "gaia_q", "value": -8.192, "time": 1717757869.87} -{"unit": "pcc_p", "value": -29.287, "time": 1717757870.795} -{"unit": "pcc_q", "value": 4.26, "time": 1717757870.795} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757870.91} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757870.91} -{"unit": "pv319_p", "value": 11.022, "time": 1717757870.985} -{"unit": "pv319_q", "value": 0.129, "time": 1717757870.985} -{"unit": "pv330_p", "value": 15.933, "time": 1717757870.88} -{"unit": "pv330_q", "value": -0.202, "time": 1717757870.88} -{"unit": "battery_p", "value": -0.22, "time": 1717757870.892} -{"unit": "battery_q", "value": 0.036, "time": 1717757870.892} -{"unit": "b2b_p", "value": -0.908, "time": 1717757870.97} -{"unit": "b2b_q", "value": 3.507, "time": 1717757870.97} -{"unit": "gaia_p", "value": 3.909, "time": 1717757871.053} -{"unit": "gaia_q", "value": -8.314, "time": 1717757871.053} -{"unit": "pcc_p", "value": -29.725, "time": 1717757872.045} -{"unit": "pcc_q", "value": 4.375, "time": 1717757872.045} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757872.0} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757872.0} -{"unit": "pv319_p", "value": 11.022, "time": 1717757871.733} -{"unit": "pv319_q", "value": 0.127, "time": 1717757872.136} -{"unit": "pv330_p", "value": 15.978, "time": 1717757871.992} -{"unit": "pv330_q", "value": -0.203, "time": 1717757871.992} -{"unit": "battery_p", "value": -0.22, "time": 1717757872.102} -{"unit": "battery_q", "value": 0.036, "time": 1717757872.102} -{"unit": "b2b_p", "value": -0.908, "time": 1717757872.185} -{"unit": "b2b_q", "value": 3.514, "time": 1717757872.185} -{"unit": "gaia_p", "value": 3.595, "time": 1717757872.173} -{"unit": "gaia_q", "value": -8.206, "time": 1717757872.173} -{"unit": "pcc_p", "value": -29.546, "time": 1717757873.125} -{"unit": "pcc_q", "value": 4.299, "time": 1717757873.125} -{"unit": "dumpload_p", "value": 0.0, "time": 1717757873.245} -{"unit": "dumpload_q", "value": 0.0, "time": 1717757873.245} -{"unit": "pv319_p", "value": 11.038, "time": 1717757873.22} -{"unit": "pv319_q", "value": 0.127, "time": 1717757873.22} -{"unit": "pv330_p", "value": 16.0, "time": 1717757873.277} -{"unit": "pv330_q", "value": -0.203, "time": 1717757873.277} -{"unit": "battery_p", "value": -0.221, "time": 1717757872.917} -{"unit": "battery_q", "value": 0.034, "time": 1717757872.917} -{"unit": "b2b_p", "value": -0.908, "time": 1717757873.298} -{"unit": "b2b_q", "value": 3.501, "time": 1717757873.298} -{"unit": "gaia_p", "value": 3.593, "time": 1717757873.269} -{"unit": "gaia_q", "value": -8.215, "time": 1717757873.269} diff --git a/data/setpoints/dummy_file b/data/setpoints/dummy_file deleted file mode 100644 index c81b66a..0000000 --- a/data/setpoints/dummy_file +++ /dev/null @@ -1 +0,0 @@ -Makes folder visible for git. \ No newline at end of file diff --git a/demo_datalogger.py b/demo_datalogger.py deleted file mode 100644 index 0d1e1e0..0000000 --- a/demo_datalogger.py +++ /dev/null @@ -1,47 +0,0 @@ -import syslab -from json import dump -from time import sleep, time - -# Defines location and name of the measurements file -LOG_FILE = f'data/measurements/measurements_{time():.00f}.json' -print(f"Logging to file {LOG_FILE}") - -# Set up a connection to the switchboards -sb3192 = syslab.SwitchBoard('319-2') -sb3193 = syslab.SwitchBoard('319-3') -sb33012 = syslab.SwitchBoard("330-12") -sb1172 = syslab.SwitchBoard('117-2') - -# Convenience function to -def take_measurements(): - measurements = { - "pcc_p": sb3192.getActivePower('Grid'), - "pcc_q": sb3192.getReactivePower('Grid'), - "pv319_p": sb3192.getActivePower('PV'), - "pv319_q": sb3192.getReactivePower('PV'), - "dumpload_p": sb3192.getActivePower('Dumpload'), - "dumpload_q": sb3192.getReactivePower('Dumpload'), - "gaia_p": sb33012.getActivePower('Gaia'), - "gaia_q": sb33012.getReactivePower('Gaia'), - "pv330_p": sb33012.getActivePower('PV_1'), - "pv330_q": sb33012.getReactivePower('PV_1'), - "b2b_p": sb3193.getActivePower('ABB_Sec'), - "b2b_q": sb3193.getReactivePower('ABB_Sec'), - "battery_p": sb1172.getActivePower('Battery'), - "battery_q": sb1172.getReactivePower('Battery'), - } - return [{'unit': k, 'value': meas.value, 'time': meas.timestampMicros/1e6} for k, meas in measurements.items()] - - -while True: - measurement = take_measurements() - - # Open the output file in "append" mode which adds lines to the end - with open(LOG_FILE, 'a') as file: - for m in measurement: - # Convert the dictionary m to a json string and put it - # in the file. - dump(m, file) - # Write a newline for each measurement to make loading easier - file.write('\n') - sleep(1) diff --git a/demo_plotter.py b/demo_plotter.py deleted file mode 100644 index 372f2fb..0000000 --- a/demo_plotter.py +++ /dev/null @@ -1,139 +0,0 @@ -import pandas as pd -import json -import matplotlib.pyplot as plt -import os -from datetime import timedelta - -## Read the measurements data file ## -DATA_MEAS_DIR = 'data\measurements' -# Always plot latest datafile - replace [-1] with another index if you want to plot a specific file. -MEAS_LOG_FILE = sorted(os.listdir(DATA_MEAS_DIR))[-1] - -# Store each dictionary of the measurements json in a list -with open(os.path.join(DATA_MEAS_DIR, MEAS_LOG_FILE)) as f: - meas_data = [json.loads(line) for line in f] - -# Use setpoint logger (only necessary for part two of the exercise "collecting fresh data") -use_setpoint_log = False - - -## Read the setpoints data file ## -if use_setpoint_log: - DATA_SP_DIR = 'data\setpoints' - # Always plot latest datafile - SP_LOG_FILE = sorted(os.listdir(DATA_SP_DIR))[-1] - - # Store each dictionary of the setpoints json in a list - with open(os.path.join(DATA_SP_DIR, SP_LOG_FILE)) as f: - sp_data = [json.loads(line) for line in f] - - # Merge measurements and setpoints in one list - data = meas_data + sp_data - -else: - data = meas_data - - -# Construct a dataframe and pivot it to obtain a dataframe with a column per unit, and a row per timestamp. -df = pd.DataFrame.from_records(data) -df_pivot = df.pivot_table(values='value', columns='unit', index='time') - - -# Plot the data. Note, that the data will mostly not be plotted with lines. -plt.ion() # Turn interactive mode on -plt.figure() -ax1 = plt.subplot(211) # Make two separate figures -ax2 = plt.subplot(212) -df_pivot[[c for c in df_pivot.columns if "_p" in c]].plot(marker='.', ax=ax1, linewidth=3) -df_pivot[[c for c in df_pivot.columns if "_q" in c]].plot(marker='.', ax=ax2, linewidth=3) -plt.show(block=True) - - -## TODO Q1: Your code here - - - - - -## TODO Q2: -# Convert time column (index) of df_pivot to datetime -# TODO Your code here -# Hint1: You can use pandas to_numeric() to prepare the index for pandas to_datetime function -# Hint2: Remember to define the unit within pandas to_datetime function - -# Resample the data -# TODO Your code here - - -# Interpolate the measurements -# TODO Your code here -# Hint: For part two of the exercise ("collecting fresh data") the nan rows after a setpoint -# in the recorded step function should be filled with the value of the setpoint until the row of the next setpoint is reached -# You can use the df.fillna(method="ffill") function for that purpose. However, the measurements should still be interpolated! - - - -# Plot the resampled data -# TODO Your code here - - - -## TODO Q3: Your code here - - - - -## TODO Q4: Your code here - - - -## Part two: "Collecting fresh data" - -# Hint 1: You can build up on the "read_and_plot_data.py" from day 2 -# Hint 2: Yoy may want to store your response metric functions from day 2 in the "util.py" and import all of them with -# "from util import *" - -if use_setpoint_log: - - # Add a column to df_pivot containing the reference/target signal - # TODO your code here - - # Loop over all steps and extract T_1, T_2 and the step size - results = {} - - for idx in range(0, len(sp_data)-1): - label = f"Step_{sp_data[idx]['value']}kW" - - # Extract T_1 and T_2 from the setpoint JSON - # TODO your code here - - - # Change timestamp format - T_1 = pd.to_datetime(pd.to_numeric(T_1), unit="s").round("0.1S") - T_2 = pd.to_datetime(pd.to_numeric(T_2), unit="s").round("0.1S") - - # To ensure we are not considering values of the next load step - T_2 = T_2 - timedelta(seconds=0.2) - - - # define measured output y and target setpoint r - # TODO your code here - - # Derive step direction from the setpoint data - if ...: # TODO your code here - Positive_step = True - else: - Positive_step = False - - # Collect response metrics results - results[label] = { - # TODO your code here - } - - pd.DataFrame.from_dict(results).plot(kind='bar') - plt.title("Metrics") - plt.tight_layout() - plt.savefig('data/test_metrics'+MEAS_LOG_FILE[-10:]+'.png') - plt.show(block=True) - - diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 0fd83a0..0000000 --- a/requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -beautifulsoup4==4.12.3 -certifi==2024.6.2 -charset-normalizer==3.3.2 -greenlet==3.0.3 -idna==3.7 -msgpack==1.0.8 -pynvim==0.5.0 -requests==2.32.3 -soupsieve==2.5 -# Editable Git install with no remote (syslab==0.3.0) --e /home/daniel/Dropbox/DTU/F24/46045/syslab/syslab-python -urllib3==2.2.1 diff --git a/syslab-python/.gitignore b/syslab-python/.gitignore deleted file mode 100644 index 1edbec7..0000000 --- a/syslab-python/.gitignore +++ /dev/null @@ -1,109 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ - -\.DS_Store - -# Pycharm -.idea/ \ No newline at end of file diff --git a/syslab-python/README.md b/syslab-python/README.md deleted file mode 100644 index 371e682..0000000 --- a/syslab-python/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# SYSLAB Python Interface - -This project provides a Python interface to several SYSLAB components. - -## Required software - -- Python (>=3.7) -- python-requests (>=2.18) -- python-bs4 (>= 4.7) - -## Installation - -To install the package in your local path, run - -```shell - python setup.py install -``` - -Alternatively, copy the `syslab` folder into your project directory. - -# Contributors - -- Anders Thavlov: Initial implementation -- Oliver Gehrke -- Daniel Esteban Morales Bondy -- Tue Vissing Jensen -- Federico Zarelli diff --git a/syslab-python/example.py b/syslab-python/example.py deleted file mode 100644 index ea97246..0000000 --- a/syslab-python/example.py +++ /dev/null @@ -1,11 +0,0 @@ -from syslab import SwitchBoard - -name = '319-2' -SB_connection = SwitchBoard(name) -print("Let's look at what is going on in the switchboard {}.".format(name)) - -for bay in range(SB_connection.getNumBays()): - print(SB_connection.getBayName(bay),' : ',SB_connection.getActivePower(bay)) - - - diff --git a/syslab-python/notes.md b/syslab-python/notes.md deleted file mode 100644 index 7065476..0000000 --- a/syslab-python/notes.md +++ /dev/null @@ -1,99 +0,0 @@ -# Notes on SOAP implementation - - - Units should reflect SOAP methods onto their own namespace (1) - - CompositeMeasurement should convert to/from SOAP - - Type checking via client.get\_type('ns0:compositeMeasurement').elements - - - -# Notes about this module - to be discussed - -SYSLAB\_Unit.py has a whole bunch of static methods - should these be split into a util library instead? -Generally, many places where static methods are used for things that should perhaps just be functions... - -The following files are empty: - - BattOpMode.py - - FlowBatteryState.py - - GaiaWindTurbine.py - - -To check the methods available, use, e.g.: -http://syslab-33.syslab.dk:8080/typebased_WebService_HeatSubstation/HeatSwitchboardWebService/716-h1/resourceNames - -To figure out this URL, look at software.xml for the corresponding machine, and use this template: - -http://(machineName).syslab.dk:(port)/(interfaceName)/(shortServerName)/(unitname)/resourceNames - -| field | corresponds to | notes | -| ----- | -------------- | ----- | -| machineName | N/A | Look this up on the wiki | -| port | N/A | Dynamically allocated, starting at 8080 - good luck! | -| interfaceName | typeBasedWebService, interfaceName | | -| shortServerName | typeBasedWebService, serverClass | Remove the "Server" at the end | -| unitname | dataLogger, unit | Also defined as "name" in hardware.xml | - - -------------------------- - - -SYSLAB COMMON -Broadcast event logger: - -Transcode to python: -https://git.elektro.dtu.dk/syslab/syslab-common/-/blob/master/src/main/java/risoe/syslab/comm/broadcast/BroadcastLogSender.java - -broadcast log sender -:: transcode the "send()" method to python. It byte-encodes the message for UDP. -Java: -send(String origin, byte[] origIP, long timestamp, int ploadType, String message, - int level, int flags, String[] tags) ------------- -Python: -----------. -def send(origin, origIP, timestamp, ploadType, message, level, flags, tags): - ploadbytes = message[:min(1024, len(message))].encode() - origbytes = origin[:min(32, len(origin))].encode() - tagbytes = tagsToBytes(tags, 256) - pktlen = 2 + 2 + 1 + len(origbytes) + 4 + 2 + 2 + 8 + 1 + 2 + len(ploadbytes) + len(tagbytes) - buf = bytearray(pktlen) - buf[0] = BroadcastLogConstants.BROADCASTLOG_PKTID >> 8 - buf[1] = BroadcastLogConstants.BROADCASTLOG_PKTID & 0xff - buf[2] = (pktlen >> 8) & 0xff - buf[3] = pktlen & 0xff - buf[4] = len(origbytes) - buf[5:5+len(origbytes)] = origbytes - writePtr = 5 + len(origbytes) - buf[writePtr:writePtr+4] = origIP - writePtr += 4 - buf[writePtr] = (level >> 8) & 0xff - buf[writePtr+1] = level & 0xff - buf[writePtr+2] = (flags >> 8) & 0xff - buf[writePtr+3] = flags & 0xff - for i in range(8): - buf[writePtr+7-i] = timestamp & 0xff - timestamp >>= 8 - writePtr += 8 - buf[writePtr] = ploadType & 0xff - buf[writePtr+1] = (len(ploadbytes) >> 8) & 0xff - buf[writePtr+2] = len(ploadbytes) & 0xff - buf[writePtr+3:writePtr+3+len(ploadbytes)] = ploadbytes - writePtr += len(ploadbytes) - buf[writePtr:writePtr+len(tagbytes)] = tagbytes - pack = n - pack = DatagramPacket(buf, len(buf), InetAddress.getByName("localhost"), 4445) - sock.send(pack) - - ------------- - -broadcast log receiver -+ needs a logger -listener ist interface for receiver - -gui wall (SYSLAB Userspacce) -broadcast log displet -https://git.elektro.dtu.dk/syslab/syslab-userspace/-/blob/master/src/main/java/risoe/syslab/gui/wall/displets/BroadcastLogDisplet.java -... maybe extend with simple log file writer. - - - - diff --git a/syslab-python/requirements.txt b/syslab-python/requirements.txt deleted file mode 100644 index 25cc339..0000000 --- a/syslab-python/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -requests >= 2.18 -beautifulsoup4 >= 3.7 \ No newline at end of file diff --git a/syslab-python/setup.cfg b/syslab-python/setup.cfg deleted file mode 100644 index 43f9acc..0000000 --- a/syslab-python/setup.cfg +++ /dev/null @@ -1,10 +0,0 @@ -[flake8] -ignore = -max-line-length = 79 -max-complexity = 11 - -[pytest] -addopts = --doctest-glob="*.rst" - -[wheel] -universal = True diff --git a/syslab-python/setup.py b/syslab-python/setup.py deleted file mode 100644 index 8c13382..0000000 --- a/syslab-python/setup.py +++ /dev/null @@ -1,36 +0,0 @@ -from setuptools import setup, find_packages - - -setup( - name='syslab', - version='0.3.0', - author='Tue Vissing Jensen', - author_email='tvjens at elektro.dtu.dk', - description=('SYSLAB webservice client library.'), - long_description=(''), - url='https://www.syslab.dk', - install_requires=[ - 'requests>=2.18', - 'beautifulsoup4>=3.7', - ], - packages=find_packages(exclude=['tests*']), - include_package_data=True, - entry_points={ - 'console_scripts': [ - ], - }, - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Environment :: Console', - 'Intended Audience :: Science/Research', - 'License :: Other/Proprietary License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Topic :: Scientific/Engineering', - 'Topic :: Software Development :: Libraries :: Python Modules', - ], -) diff --git a/syslab-python/syslab/__init__.py b/syslab-python/syslab/__init__.py deleted file mode 100644 index c7b2d33..0000000 --- a/syslab-python/syslab/__init__.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -SYSLAB library -~~~~~~~~~~~~~~~~~~~~~ - -SYSLAB is a Python 3 library for control and monitoring of units in SYSLAB. Usage of this library requires the running -computer to be located in the SYSLAB network, either physically or virtually, ie. using a VPN connection. - - -""" - -__title__ = 'syslab' -__version__ = '0.3.0' -__author__ = 'Anders Thavlov, Daniel Esteban Morales Bondy, Tue Vissing Jensen' - -__maintainer__ = 'Tue Vissing Jensen' -__license__ = '' -__copyright__ = 'DTU' - -# Raise error if we are not on Python 3 -import sys -if not (sys.version_info.major == 3 and sys.version_info.minor >= 5): - raise RuntimeError("Must be using at least Python 3.5") - -# DataTypes -from .core.datatypes import CompositeMeasurement -from .core.datatypes import CompositeBoolean - -# Physical units -from .physical import \ - SwitchBoard, \ - Dumpload, \ - Photovoltaics, \ - Battery, \ - HeatSwitchBoard, \ - WindTurbine, \ - DieselGenerator, \ - B2BConverter, \ - MeteoMast, \ - EVSE - -# Logging utilities -#from .comm.LogUtils import e \ No newline at end of file diff --git a/syslab-python/syslab/comm/LogUtils.py b/syslab-python/syslab/comm/LogUtils.py deleted file mode 100644 index b755d43..0000000 --- a/syslab-python/syslab/comm/LogUtils.py +++ /dev/null @@ -1,59 +0,0 @@ -############################################################### -# SYSLAB remote logging utilities v0.9 -# collect and record log events -# -# Author: Kai Heussen -# Date: 2023/06/18 -############################################################### -import logging -import logging.handlers -import time -import syslab.config as config - -event_log_formats = '%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(funcName)s - %(message)s' -simple_log_formats = '%(asctime)s - %(name)s - %(message)s' - -def setup_event_logger(loggername=config.EVLOG_NAME, host='localhost', port=config.REMOTE_PORT_EV, level=logging.INFO, formats=simple_log_formats): # UDP - handler1 = logging.handlers.DatagramHandler(config.REMOTE_IP_EV, config.REMOTE_PORT_EV) - handler2 = logging.handlers.DatagramHandler(host, port) - handler3 = logging.StreamHandler() - formatter = logging.Formatter(formats) - handler3.setFormatter(formatter) - loggr = logging.getLogger(loggername) - loggr.setLevel(level) - loggr.addHandler(handler1) - loggr.addHandler(handler2) - loggr.addHandler(handler3) - return loggr - - -def setup_local_logger(loggername=config.EVLOG_NAME, host='localhost', port=config.REMOTE_PORT_EV, level=logging.INFO, formats=simple_log_formats): # UDP - handler = logging.handlers.DatagramHandler(host, port) - formatter = logging.Formatter(formats) - handler.setFormatter(formatter) - loggr = logging.getLogger(loggername) - loggr.setLevel(level) - loggr.addHandler(handler) - return loggr - - -def setup_udp_logger(loggername=config.SPLOG_NAME, host=config.REMOTE_IP_SP, port=config.REMOTE_PORT_SP, level=logging.INFO, formats=config.LOG_FORMATS): # UDP - handler = logging.handlers.DatagramHandler(host, port) - formatter = logging.Formatter(formats) - handler.setFormatter(formatter) - loggr = logging.getLogger(loggername) - loggr.setLevel(level) - loggr.addHandler(handler) - return loggr - - -if __name__ == "__main__": - logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(levelname)-8s %(message)s') - - # logging.getLogger().addHandler(logging.handlers.DatagramHandler('10.42.242.3', 51010)) - logger = setup_local_logger() - while True: - logger.debug("This shouldn't show up") - logger.info("This should show up") - time.sleep(3) diff --git a/syslab-python/syslab/comm/__init__.py b/syslab-python/syslab/comm/__init__.py deleted file mode 100644 index 0c228b5..0000000 --- a/syslab-python/syslab/comm/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#from BroadcastLogger import BroadcastLogSender -#from LogUtils import setup_udp_logger \ No newline at end of file diff --git a/syslab-python/syslab/comm/logrec.py b/syslab-python/syslab/comm/logrec.py deleted file mode 100644 index 6f35820..0000000 --- a/syslab-python/syslab/comm/logrec.py +++ /dev/null @@ -1,80 +0,0 @@ -############################################################### -# SYSLAB remote logger v0.9 -# utility to display and record log events -# usage: move bash to target log directory, then call -# python /syslab/comm/logrec.py -# -# Author: Kai Heussen -# Date: 2023/06/18 -############################################################### -import pickle -import logging -import socket -from syslab import config -# import sys -from time import time -# from json import dump - -BASIC = True -FILE = True -FILE_RAW = False # TODO: write a JSON formatter - based on https://stackoverflow.com/questions/50144628/python-logging-into-file-as-a-dictionary-or-json - -logtype = "EV" -time=time() -logfile =f"syslab_{logtype}_log_{time:.00f}.txt" -logfile_raw =f"syslab_{logtype}_log_{time:.00f}.raw" # not yet json - -DEFAULT_PORT = config.REMOTE_PORT_SP if logtype == "SP" else config.REMOTE_PORT_EV - -port = DEFAULT_PORT - -#simple_formats = '%(asctime)s - %(name)s - %(message)s' -simple_formats = '%(asctime)s - %(module)s - %(message)s' -#formats='foo: %(levelname)s - %(module)s.%(funcName)s - %(message)s' -event_log_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(module)s - %(funcName)s - %(message)s' - -formats = simple_formats -formatter = logging.Formatter(formats) - -if BASIC: - logging.basicConfig(format=formats) -else: - handler = logging.StreamHandler() - handler.setLevel(logging.DEBUG) - handler.setFormatter(formatter) - logging.getLogger().addHandler(handler) - -if FILE: - handler = logging.FileHandler(logfile) - handler.setLevel(logging.INFO) - handler.setFormatter(formatter) - logging.getLogger().addHandler(handler) - - -logger = logging.getLogger() - -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -s.bind(('', port)) - -print(f'Listening for log records on port {port}...') -if FILE: - print(f'recording log entries in file: {logfile}') -if FILE_RAW: - print(f'recording raw log entries in file: {logfile_raw}') - -try: - while True: - d, _ = s.recvfrom(1024) - msg = pickle.loads(d[4:]) - logrec = logging.makeLogRecord(msg) - logger.handle(logrec) - if FILE_RAW: - with open(logfile_raw, 'a') as file: - # dump(logrec, file) # requires a JSON formatter - file.write(f'{logrec.__str__() }\n') # Write a newline for each measurement to make loading easier - #print(log) -finally: - s.close() - if FILE_RAW: - file.close() - diff --git a/syslab-python/syslab/config.py b/syslab-python/syslab/config.py deleted file mode 100644 index 3f2c2db..0000000 --- a/syslab-python/syslab/config.py +++ /dev/null @@ -1,19 +0,0 @@ -DEBUG = False -SPLOG_NAME = 'SetPointLogger' -EVLOG_NAME = 'EventLog' -REMOTE_LOGGER = True -REMOTE_IP_SP = '10.42.242.3' # UI Machine 03 -REMOTE_IP_EV = '10.42.242.3' # UI Machine 03 -REMOTE_PORT_SP = 51010 -REMOTE_PORT_EV = 51020 -LOCAL_IP = 'localhost' -LOCAL_PORT_SP = 51010 -LOCAL_PORT_EV = 51020 -LOCAL_LOGGER = False -LOG_FORMATS = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' # '%(asctime)s %(levelname)-8s %(message)s' -TEST_LOCAL = False -if TEST_LOCAL: - REMOTE_PORT_SP = LOCAL_PORT_SP - REMOTE_PORT_EV = LOCAL_PORT_EV - REMOTE_IP_SP = LOCAL_IP - REMOTE_IP_EV = LOCAL_IP diff --git a/syslab-python/syslab/core/SyslabUnit.py b/syslab-python/syslab/core/SyslabUnit.py deleted file mode 100644 index 5d7d832..0000000 --- a/syslab-python/syslab/core/SyslabUnit.py +++ /dev/null @@ -1,306 +0,0 @@ -from .datatypes import CompositeBoolean, BattOpMode, CompositeMeasurement -from .datatypes import FlowBatteryState, ConvState, ConvOpMode -from .datatypes import HeatCirculationPumpMode, HeatCirculationPumpState -import syslab.config as config - - -class SyslabUnit: - __HIDDEN_RESOURCES = { - 'authenticate': ('boolean', 'String', 'String'), - 'isAuthenticated': ('boolean',), - 'checkConnection': ('boolean',), - 'logout': ('void',)} - - def __init__(self, baseurl, units=None, which=None, host=None, port=None, unit_name=None, unit_type=""): - """ - Initialize a proxy to the given unit. - - :param baseurl: Example: 'http://{host}:{port}/typebased_WebService_Battery/VRBBatteryWebService/{unit_name}/' - :param units: dictionary of units to be loaded in the format {'which': ('host', 'port', 'unit_name')} - :param which: string indicating which unit we pick from _units_ - :param host: (optional) override host - :param port: (optional) override port - :param unit_name: (optional) override unit_name - :param unit_type: (optional) Used to indicate the type of the unit. - """ - - if units is None: - units = {} - - if which is not None: - if which not in units: - raise TypeError( - 'The {unit_type} should be one of: "{list_of_units}"'.format( - unit_type=unit_type, - list_of_units='", "'.join(units.keys()) - )) - else: - host, port, unit_name = units.get(which) - if host is not None: - host = host - if port is not None: - port = port - - assert host is not None, "When assigning custom port, host must not be None." - assert port is not None, "When assigning custom host, port must not be None." - assert unit_name is not None, "When assigning custom host and port, unit_name must not be None." - - url = baseurl.format(host=host, port=port, unit_name=unit_name) - print(url) - self._url = url - self._resources = parse_resources(url) - self._resources = {**self._resources, **SyslabUnit.__HIDDEN_RESOURCES} - # TODO: Do type checking on these types. Ignore for now - self._complex_arg_types = ['BattOpMode', 'CompositeMeasurement', 'HeatCirculationPumpMode'] - - - if config.REMOTE_LOGGER: - #import logger - if config.DEBUG: - print(f"Setting up remote logger with default IP: {config.REMOTE_IP} and port: {config.REMOTE_PORT}") - from uuid import uuid1, getnode - from ..comm.LogUtils import setup_udp_logger - self.__logger = setup_udp_logger(config.SPLOG_NAME) - self.__session_id = uuid1().__str__() - self.__host_id = getnode().__str__() - - # TODO: Set up local setpoints Logger - if config.LOCAL_LOGGER: - pass - - def __request_int(self, resource, method, args, body) -> int: - return int(send_request(self._url, resource, method, args, body)) - - def __request_float(self, resource, method, args, body) -> float: - return float(send_request(self._url, resource, method, args, body)) - - def __request_boolean(self, resource, method, args, body) -> bool: - return bool(send_request(self._url, resource, method, args, body)) - - def __request_string(self, resource, method, args, body) -> str: - return send_request(self._url, resource, method, args, body) - - def __request_void(self, resource, method, args, body) -> None: - send_request(self._url, resource, method, args, body) - - def __request_composite_boolean(self, resource, method, args, body) -> CompositeBoolean: - - if self.__get_resource_return_type(resource) == 'CompositeBoolean': - json_string = self.__request_string(resource, method, args, body) - result = CompositeBoolean.parseFromJSON(json_string) - else: - raise TypeError('Error: resource "{0}" does not return a CompositeBoolean.'.format(resource)) - - return result - - def __request_composite_measurement(self, resource, method, args, body) -> CompositeMeasurement: - - if self.__get_resource_return_type(resource) == 'CompositeMeasurement': - json_string = self.__request_string(resource, method, args, body) - result = CompositeMeasurement.parseFromJSON(json_string) - else: - raise TypeError('Error: resource "{0}" does not return a CompositeMeasurement.'.format(resource)) - - return result - - def _request_resource(self, resource, args=(), method='get', body=None, check_types=True): - if not type(resource) is str: - raise TypeError("Resource should be a string, found {0}.".format(type(resource))) - - if resource not in self._resources: - # print(resource) - # FIXME: Workaround for metmast, where string-based methods are suffixed by a '2' and int-based methods by a '1' - if not resource[-1] in ('1', '2'): - raise ValueError('Unknown resource: {0} - no such resource found for {1}'.format(resource, self._url)) - - if type(args) is int or type(args) is float or type(args) is str: - args = (args,) - - if config.DEBUG: - print("Resource: ", resource, " and args: ", args, "with method: ", method) - - if config.REMOTE_LOGGER and method == 'put': - logstr = f'SessionID:{self.__session_id}||SenderID:{self.__host_id}||Unit-URL:{self._url}||Setterfcn:{resource}||ArgValue:{args}' - self.__logger.info(logstr) - - return_type = self.__get_resource_return_type(resource) - self.__check_argument(resource, args) - result = None - - if check_types: - try: - if return_type == 'CompositeMeasurement': - result = self.__request_composite_measurement(resource, method, args, body) - elif return_type == 'CompositeBoolean': - result = self.__request_composite_boolean(resource, method, args, body) - elif return_type == 'String': - result = self.__request_string(resource, method, args, body) - elif return_type == 'int': - result = self.__request_int(resource, method, args, body) - elif return_type == 'boolean': - result = self.__request_boolean(resource, method, args, body) - elif return_type == 'float' or return_type == 'double': - result = self.__request_float(resource, method, args, body) - elif return_type == 'void': - self.__request_string(resource, method, args, body) - elif return_type == 'BattOpMode': - result = BattOpMode.parseFromJSON(self.__request_string(resource, method, args, body)) - elif return_type == 'FlowBatteryState': - result = FlowBatteryState.parseFromJSON(self.__request_string(resource, method, args, body)) - elif return_type == 'ConvState': - result = ConvState.parseFromJSON(self.__request_string(resource, method, args, body)) - elif return_type == 'EVSEState': - result = EVSEState.parseFromJSON(self.__request_string(resource, method, args, body)) - elif return_type == 'ConvOpMode': - result = ConvOpMode.parseFromJSON(self.__request_string(resource, method, args, body)) - elif return_type == 'HeatCirculationPumpMode': - result = HeatCirculationPumpMode.parseFromJSON(self.__request_string(resource, method, args, body)) - elif return_type == 'HeatCirculationPumpState': - result = HeatCirculationPumpState.parseFromJSON(self.__request_string(resource, method, args, body)) - elif return_type == 'WYEV' or return_type == 'WYEA' or return_type == 'DELV': - import json - result = json.loads(self.__request_string(resource, method, args, body)) - else: - raise TypeError( - 'TypeError: The return type {0} by {1} is unknown or not supported yet.'.format(return_type, - resource)) - except KeyError as e: - # raise e - raise ValueError('{0} - no such resource found for {1}'.format(resource, self._url)) - else: - import json - return_string = self.__request_string(resource, method, args, body) - try: - result = json.loads(return_string) - except RecursionError: - raise RecursionError( - "Maximum recursion depth exceeded while decoding " - "a JSON array from a unicode string. Length: {0}".format( - len(return_string))) - - return result - - def __get_resource_return_type(self, resource): - if not resource[-1] in ('1', '2'): - # FIXME: Workaround for metmast, where string-based methods are suffixed by a '2' and int-based methods by a '1' - return self._resources[resource][0] - else: - return self._resources[resource[:-1]][0] - - def __get_resource_argument_types(self, resource): - if not resource[-1] in ('1', '2'): - # FIXME: Workaround for metmast, where string-based methods are suffixed by a '2' and int-based methods by a '1' - return self._resources[resource][1:] - else: - return self._resources[resource[:-1]][1:] - - def __check_argument(self, resource, args): - arg_types = self.__get_resource_argument_types(resource) - try: - # TODO Ignore complex arguments (for now) - for complex_arg_type in self._complex_arg_types: - if complex_arg_type in arg_types: - return - - if len(args) == len(arg_types): - for arg, arg_type in zip(args, arg_types): - - if arg_type == 'String' and type(arg) is not str: - raise TypeError() - elif arg_type == 'int' and type(arg) is not int: - raise TypeError() - elif (arg_type == 'float' or arg_type == 'double') and type(arg) is not float and type( - arg) is not int: - raise TypeError() - else: - raise TypeError() - - except TypeError: - raise TypeError( - 'The resource "{0}" requires exactly {1} argument(s) of type {2}.'.format(resource, len(arg_types), - arg_types)) - - -def parse_resources(url): - import re - from ast import literal_eval - result = {} - resources = send_request(url, 'resourceNames', 'get') - resources = literal_eval(resources) - - for resource in resources: - try: - # TODO - handle java arrays, ie, [] - m = re.match("(\w+)\[?\]? (\w+)(\([\w ,]*\))?", resource).groups() - except AttributeError as e: - print(e) - continue - args = '' - - if m[2] is not None: - args = tuple(m[2].replace(' ', '').replace('(', '').replace(')', '').split(',')) - result[m[1]] = (m[0],) + args - else: - result[m[1]] = (m[0],) - if config.DEBUG: - print(f'Key: {m[1]} - {m[0]} -- {args}') - - return result - - -def send_request(url, resource, method, args=None, body=None): - from requests import request - from requests.exceptions import ConnectionError, RequestException - - if not type(url) is str: - raise TypeError('URL should be a string, found {0}'.format(type(url))) - if not type(resource) is str: - raise TypeError('URL should be a string, found {0}'.format(type(resource))) - - kwargs = {} - kwargs.setdefault('allow_redirects', True) - kwargs.setdefault('headers', {'accept': 'application/json', 'content-type': 'application/json'}) - - if not url.endswith('/'): - url += '/' - - full_url = url + resource + '/' - - if args is not None and len(args) > 0: - full_url += '/'.join(tuple(str(x) for x in args)) - - if config.DEBUG: - print(f'Calling: {full_url}') - - try: - response = request(method, full_url, data=body, **kwargs) - except ConnectionError as e: - print('Unable to connect to host: {0}.'.format(url)) - raise e - except RequestException as e: - print('Request error from host: {0}.'.format(full_url)) - raise e - - if 200 <= response.status_code < 300: - result = response.text - elif response.status_code == 404: - raise ConnectionError( - 'Resource not found on host or arguments are not formatted correctly: {0}'.format(response.text)) - elif response.status_code == 405: - raise ConnectionError('Method not allowed on host: \n {0}'.format(response.text)) - elif response.status_code == 500: - from pprint import pprint - # TODO: Handle exception - print('Exception on server:') - pprint(response.json()) - raise - else: - raise ConnectionError( - 'Unable to successfully connect to host. Returned with HTTP status code {0}.\n Content: {1}'.format( - response.status_code, response.text)) - - if config.DEBUG: - print(f'Succesfully called {full_url}') - print(f'Returned: {result}') - - return result diff --git a/syslab-python/syslab/core/__init__.py b/syslab-python/syslab/core/__init__.py deleted file mode 100644 index 1e136c6..0000000 --- a/syslab-python/syslab/core/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import * diff --git a/syslab-python/syslab/core/datatypes/BattOpMode.py b/syslab-python/syslab/core/datatypes/BattOpMode.py deleted file mode 100644 index 285a31b..0000000 --- a/syslab-python/syslab/core/datatypes/BattOpMode.py +++ /dev/null @@ -1,47 +0,0 @@ - -class BattOpMode: - - _OPMODES = { - 0: 'BATT_UNKNOWN', - 1: 'BATT_AUTO', - 2: 'BATT_AUTO_SUBMODE1', - 3: 'BATT_AUTO_SUBMODE2', - 4: 'BATT_AUTO_SUBMODE3', - 5: 'BATT_AUTO_SUBMODE4', - 6: 'BATT_MANUAL', - 7: 'BATT_OFF', - 8: 'BATT_NOBMS', - 9: 'BATT_WITHBMS', } - - def __init__(self, mode): - assert mode in BattOpMode.__OPMODES - self._mode = mode - - @property - def mode(self): - return self._mode - - def modeAsString(self): - return BattOpMode.__OPMODES[self.mode] - - def __str__(self): - return 'BattOpMode: {0} ({1})'.format(self.mode, BattOpMode.__OPMODES[self.mode]) - - def parseToJSON(self): - from json import dumps - jsonObj = {}; - jsonObj['mode'] = self.mode; - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - # result = None ## Appears unused - - try: - jsonObj = loads(jsonString) - return BattOpMode(jsonObj.get('mode')) - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/CommonDeviceConfig.py b/syslab-python/syslab/core/datatypes/CommonDeviceConfig.py deleted file mode 100644 index 09fcbd2..0000000 --- a/syslab-python/syslab/core/datatypes/CommonDeviceConfig.py +++ /dev/null @@ -1,5 +0,0 @@ - - -# TODO: Implement -class CommonDeviceConfig: - pass diff --git a/syslab-python/syslab/core/datatypes/CompositeBoolean.py b/syslab-python/syslab/core/datatypes/CompositeBoolean.py deleted file mode 100644 index 4caa4f9..0000000 --- a/syslab-python/syslab/core/datatypes/CompositeBoolean.py +++ /dev/null @@ -1,68 +0,0 @@ -class CompositeBoolean: - def __init__(self, value, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - self._value = value - self._timestampMicros = timestampMicros - self._timePrecision = timePrecision if timePrecision != None else 0 - self._quality = quality if quality != None else 0 - self._validity = validity if validity != None else 0 - self._source = source if source != None else 0 - - @property - def value(self): - return self._value - - @property - def timestampMicros(self): - return self._timestampMicros - - @property - def timePrecision(self): - return self._timePrecision - - @property - def quality(self): - return self._quality - - @property - def validity(self): - return self._validity - - @property - def source(self): - return self._source - - def __repr__(self): - return "{0}(".format(self.__class__.__name__) + \ - "{0!r}, {1!r}, ".format(self._value, self._timestampMicros) + \ - "{0!r}, {1!r}, ".format(self._timePrecision, self._quality) + \ - "{0!r}, {1!r})".format(self._validity, self._source) - - def __str__(self): - from datetime import datetime - return 'CompositeBoolean: {0} (@time: {1} UTC) '.format(self.value, datetime.utcfromtimestamp(self.timestampMicros/1000000)) - - def parseToJSON(self): - from json import dumps - jsonObj = {}; - jsonObj['value'] = self.value; - jsonObj['timestampMicros'] = self.timestampMicros; - jsonObj['timePrecision'] = self.timePrecision - jsonObj['quality'] = self.quality - jsonObj['validity'] = self.validity - jsonObj['source'] = self.source; - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - try: - jsonObj = loads(jsonString) - result = CompositeBoolean(jsonObj.get('value'), jsonObj.get('timestampMicros'), - jsonObj.get('timePrecision'), - jsonObj.get('quality'), jsonObj.get('validity'), jsonObj.get('source')) - return result - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/CompositeMeasurement.py b/syslab-python/syslab/core/datatypes/CompositeMeasurement.py deleted file mode 100644 index 76a5263..0000000 --- a/syslab-python/syslab/core/datatypes/CompositeMeasurement.py +++ /dev/null @@ -1,75 +0,0 @@ -MICROS_PER_SECOND = 1000000 - -def none_to_zero(x): - if x is None: - return 0 - return x - -class CompositeMeasurement: - def __init__(self, value, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - self._value = value - self._timestampMicros = timestampMicros - self._timePrecision = none_to_zero(timePrecision) - self._quality = quality if quality != None else 0 - self._validity = validity if validity != None else 0 - self._source = source if source != None else 0 - - @property - def value(self): - return self._value - - @property - def timestampMicros(self): - return self._timestampMicros - - @property - def timePrecision(self): - return self._timePrecision - - @property - def quality(self): - return self._quality - - @property - def validity(self): - return self._validity - - @property - def source(self): - return self._source - - def __str__(self): - from datetime import datetime - return 'CompositeMeasurement: {0} (@time: {1})'.format(self.value, datetime.fromtimestamp(self.timestampMicros/MICROS_PER_SECOND)) - - def __repr__(self): - return "{0}(".format(self.__class__.__name__) + \ - "{0!r}, {1!r}, ".format(self._value, self._timestampMicros) + \ - "{0!r}, {1!r}, ".format(self._timePrecision, self._quality) + \ - "{0!r}, {1!r})".format(self._validity, self._source) - - def parseToJSON(self): - from json import dumps - jsonObj = {}; - jsonObj['value'] = self.value; - jsonObj['timestampMicros'] = self.timestampMicros; - jsonObj['timePrecision'] = self.timePrecision - jsonObj['quality'] = self.quality - jsonObj['validity'] = self.validity - jsonObj['source'] = self.source; - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - try: - jsonObj = loads(jsonString) - result = CompositeMeasurement(jsonObj.get('value'), jsonObj.get('timestampMicros'), - jsonObj.get('timePrecision'), - jsonObj.get('quality'), jsonObj.get('validity'), jsonObj.get('source')) - return result - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/CompositeStatus.py b/syslab-python/syslab/core/datatypes/CompositeStatus.py deleted file mode 100644 index e5af1e5..0000000 --- a/syslab-python/syslab/core/datatypes/CompositeStatus.py +++ /dev/null @@ -1,5 +0,0 @@ -# TODO: Add Processing here - - -class CompositeStatus: - pass diff --git a/syslab-python/syslab/core/datatypes/ConverterTypes.py b/syslab-python/syslab/core/datatypes/ConverterTypes.py deleted file mode 100644 index 6073522..0000000 --- a/syslab-python/syslab/core/datatypes/ConverterTypes.py +++ /dev/null @@ -1,132 +0,0 @@ -from .CompositeStatus import CompositeStatus - -class ConvOpMode: - - _OPMODES = { - 0: 'CONV_UNKNOWN', - 1: 'CONV_PQ', - 2: 'CONV_UF', - 3: 'CONV_OFF', - } - - def __init__(self, status, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - assert status in ConvOpMode._OPMODES - self._status = status - self._timestampMicros = timestampMicros - self._timePrecision = timePrecision - self._quality = quality - self._validity = validity - self._source = source - - @property - def mode(self) -> int: - return self._status - - def modeAsString(self): - return ConvOpMode._OPMODES[self.mode] - - def __str__(self): - return f'ConvOpMode({self.mode}; {ConvOpMode._OPMODES[self.mode]})' - - def parseToJSON(self): - from json import dumps - jsonObj = {'mode': self.mode} - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - if not type(jsonString) is str: - raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - try: - jsonObj = loads(jsonString) - return ConvOpMode(**jsonObj.get('mode')) - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e - - -class ConvState: - - _STATES = { - 0: 'CONV_UNKNOWN', - 1: 'CONV_STOPPED', - 2: 'CONV_STARTING', - 4: 'CONV_RUNNING', - 8: 'CONV_STOPPING', - 16: 'CONV_SYNCED', - 32: 'CONV_DROOP', - 64: 'CONV_LOADENABLED', - 128: 'CONV_INHIBITED', - 1024: 'CONV_READY', - 2048: 'CONV_WARNING', - 4096: 'CONV_ALARM'} - - def __init__(self, status, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - self._status = status - self._timestampMicros = timestampMicros - self._timePrecision = timePrecision - self._quality = quality - self._validity = validity - self._source = source - - @property - def status(self): - return self._status - - @property - def timestampMicros(self): - return self._timestampMicros - - @property - def timePrecision(self): - return self._timePrecision - - @property - def quality(self): - return self._quality - - @property - def validity(self): - return self._validity - - @property - def source(self): - return self._source - - def statusAsString(self): - return ConvState._STATES[self.status] - - def __repr__(self): - return "{0}(".format(self.__class__.__name__) + \ - "{0!r}, {1!r}, ".format(self._status, self._timestampMicros) + \ - "{0!r}, {1!r}, ".format(self._timePrecision, self._quality) + \ - "{0!r}, {1!r})".format(self._validity, self._source) - - def __str__(self): - from datetime import datetime - return 'FlowBatteryState: {0} : {1} (@time: {2}))'.format( - self._status, - # status & statuscode evaluates to True if statuscode is 2^k and in the binary expansion of status - ";".join([label for statuscode, label in ConvState._STATES.items() if self._status & statuscode]), - datetime.fromtimestamp(self.timestampMicros / 1000000)) - - def parseToJSON(self): - from json import dumps - json_obj = {'status': self._status} - return dumps(json_obj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - # result = None - try: - jsonObj = loads(jsonString).get('status') - return ConvState( - jsonObj.get('status'), jsonObj.get('timestampMicros'), - jsonObj.get('timePrecision'), - jsonObj.get('quality'), jsonObj.get('validity'), jsonObj.get('source')) - except JSONDecodeError as e: - print('Not a valid JSON string in parsing Converter Status: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/EVSEState.py b/syslab-python/syslab/core/datatypes/EVSEState.py deleted file mode 100644 index bb55ba3..0000000 --- a/syslab-python/syslab/core/datatypes/EVSEState.py +++ /dev/null @@ -1,83 +0,0 @@ - -class EVSEState: - - _STATES = { - 0: 'EVSE_UNKNOWN', - 1: 'EVSE_NO_EV', - 2: 'EVSE_EV_STOPPED', - 4: 'EVSE_EV_READY', - 8: 'EVSE_EV_STARTING', - 16: 'EVSE_EV_CHARGING', - 32: 'EVSE_EV_DISCHARGING', - 64: 'EVSE_EV_PAUSED', - 128: 'EVSE_EV_ALARM', - 256: 'EVSE_EV_ESD', } - - def __init__(self, status, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - self._status = status - self._timestampMicros = timestampMicros - self._timePrecision = timePrecision - self._quality = quality - self._validity = validity - self._source = source - - @property - def status(self): - return self._status - - @property - def timestampMicros(self): - return self._timestampMicros - - @property - def timePrecision(self): - return self._timePrecision - - @property - def quality(self): - return self._quality - - @property - def validity(self): - return self._validity - - @property - def source(self): - return self._source - - def statusAsString(self): - return EVSEState.__STATES[self.status] - - def __repr__(self): - return "{0}(".format(self.__class__.__name__) + \ - "{0!r}, {1!r}, ".format(self._status, self._timestampMicros) + \ - "{0!r}, {1!r}, ".format(self._timePrecision, self._quality) + \ - "{0!r}, {1!r})".format(self._validity, self._source) - - def __str__(self): - from datetime import datetime - return 'EVSEState: {0} : {1} (@time: {2}))'.format( - self.status, - # status & statuscode evaluates to True if statuscode is 2^k and in the binary expansion of status - ";".join([label for statuscode, label in EVSEState._STATES.items() if self._status & statuscode]), - datetime.fromtimestamp(self.timestampMicros / 1000000)) - - def parseToJSON(self): - from json import dumps - jsonObj = {'status': self.status} - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - # result = None - try: - jsonObj = loads(jsonString).get('status') - return EVSEState( - jsonObj.get('status'), jsonObj.get('timestampMicros'), - jsonObj.get('timePrecision'), - jsonObj.get('quality'), jsonObj.get('validity'), jsonObj.get('source')) - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/FlowBatteryState.py b/syslab-python/syslab/core/datatypes/FlowBatteryState.py deleted file mode 100644 index 6cc5a42..0000000 --- a/syslab-python/syslab/core/datatypes/FlowBatteryState.py +++ /dev/null @@ -1,88 +0,0 @@ - -class FlowBatteryState: - - _STATES = { - 0: 'BATT_UNKNOWN', - 1: 'BATT_STOPPED', - 2: 'BATT_STARTING', - 4: 'BATT_FLOODING', - 8: 'BATT_RUNNING', - 16: 'BATT_STOPPING', - 32: 'BATT_DRAINING', - 64: 'BATT_PUMPSRAMP', - 128: 'BATT_TANKVALVESOP', - 256: 'BATT_PUMPSRUN', - 512: 'BATT_DCBREAKER', - 1024: 'PCS_READY', - 2048: 'PCS_RUNNING', - 4096: 'BATT_ALARM', - 8192: 'BATT_ESD'} - - def __init__(self, status, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - self._status = status - self._timestampMicros = timestampMicros - self._timePrecision = timePrecision - self._quality = quality - self._validity = validity - self._source = source - - @property - def status(self): - return self._status - - @property - def timestampMicros(self): - return self._timestampMicros - - @property - def timePrecision(self): - return self._timePrecision - - @property - def quality(self): - return self._quality - - @property - def validity(self): - return self._validity - - @property - def source(self): - return self._source - - def statusAsString(self): - return FlowBatteryState.__STATES[self.status] - - def __repr__(self): - return "{0}(".format(self.__class__.__name__) + \ - "{0!r}, {1!r}, ".format(self._status, self._timestampMicros) + \ - "{0!r}, {1!r}, ".format(self._timePrecision, self._quality) + \ - "{0!r}, {1!r})".format(self._validity, self._source) - - def __str__(self): - from datetime import datetime - return 'FlowBatteryState: {0} : {1} (@time: {2}))'.format( - self.status, - # status & statuscode evaluates to True if statuscode is 2^k and in the binary expansion of status - ";".join([label for statuscode, label in FlowBatteryState._STATES.items() if self._status & statuscode]), - datetime.fromtimestamp(self.timestampMicros / 1000000)) - - def parseToJSON(self): - from json import dumps - jsonObj = {'status': self.status} - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - # result = None - try: - jsonObj = loads(jsonString).get('status') - return FlowBatteryState( - jsonObj.get('status'), jsonObj.get('timestampMicros'), - jsonObj.get('timePrecision'), - jsonObj.get('quality'), jsonObj.get('validity'), jsonObj.get('source')) - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/HeatCirculationPumpMode.py b/syslab-python/syslab/core/datatypes/HeatCirculationPumpMode.py deleted file mode 100644 index 0b08ccb..0000000 --- a/syslab-python/syslab/core/datatypes/HeatCirculationPumpMode.py +++ /dev/null @@ -1,89 +0,0 @@ - -class HeatCirculationPumpMode: - - __OPMODES = { - -1: 'PUMP_MODE_UNKNOWN', - 0: 'PUMP_MODE_CONSTANT_SPEED', - 1: 'PUMP_MODE_CONSTANT_FREQUENCY', - 3: 'PUMP_MODE_CONSTANT_HEAD', - 4: 'PUMP_MODE_CONSTANT_PRESSURE', - 5: 'PUMP_MODE_CONSTANT_DIFF_PRESSURE', - 6: 'PUMP_MODE_PROPORTIONAL_PRESSURE', - 7: 'PUMP_MODE_CONSTANT_FLOW', - 8: 'PUMP_MODE_CONSTANT_TEMP', - 10: 'PUMP_MODE_CONSTANT_LEVEL', - 128: 'PUMP_MODE_AUTO_ADAPT', - 129: 'PUMP_MODE_FLOW_ADAPT' } - - __OPMODES_R = {v: k for k, v in __OPMODES.items()} - - def __init__(self, status, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - """ - @Input: - mode (int or str): Pump operating mode, can be both int and string - - To get list of available modes: HeatCirculationPumpMode.opmodes() - """ - if status in HeatCirculationPumpMode.__OPMODES: - self._status = status - elif mode in HeatCirculationPumpMode.__OPMODES_R: - self._status = HeatCirculationPumpMode.__OPMODES_R[status] - else: - raise AssertionError('HeatCirculationPumpMode not recognized: \'{0}\''.format(mode)) - self._timestampMicros = timestampMicros - self._timePrecision = timePrecision - self._quality = quality - self._validity = validity - self._source = source - - @staticmethod - def opmodes(): - return HeatCirculationPumpMode.__OPMODES.copy() - - @property - def mode(self): - return self._status - - @property - def modeAsString(self): - return HeatCirculationPumpMode.__OPMODES[self.mode] - - def __repr__(self): - return "{0}(".format(self.__class__.__name__) + \ - "{0!r}, {1!r}, ".format(self._status, self._timestampMicros) + \ - "{0!r}, {1!r}, ".format(self._timePrecision, self._quality) + \ - "{0!r}, {1!r})".format(self._validity, self._source) - def __str__(self): - return 'HeatCirculationPumpMode: {0} ({1})'.format(self.mode, self.modeAsString) - - def parseToJSON(self): - from json import dumps - jsonObj = {}; - jsonObj['mode'] = { - 'status': self._status, - 'timestampMicros': self._timestampMicros, - 'timePrecision': self._timePrecision, - 'quality': self._quality, - 'validity': self._validity, - 'source': self._source, - } - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - # result = None ## Appears unused - - try: - jsonObj = loads(jsonString).get('mode') - return HeatCirculationPumpMode( - jsonObj.get('status'), - jsonObj.get('timestampMicros'), - jsonObj.get('timePrecision'), - jsonObj.get('quality'), - jsonObj.get('validity'), - jsonObj.get('source')) - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/HeatCirculationPumpState.py b/syslab-python/syslab/core/datatypes/HeatCirculationPumpState.py deleted file mode 100644 index 2628b16..0000000 --- a/syslab-python/syslab/core/datatypes/HeatCirculationPumpState.py +++ /dev/null @@ -1,83 +0,0 @@ - -class HeatCirculationPumpState: - - __OPSTATES = { - -1: 'PUMP_STATE_UNKNOWN', - 0: 'PUMP_STATE_STOPPED', - 1: 'PUMP_STATE_RUNNING', - 2: 'PUMP_STATE_ERROR',} - __OPSTATES_R = {v: k for k, v in __OPSTATES.items()} - - def __init__(self, status, timestampMicros, timePrecision=0, quality=0, validity=0, source=0): - """ - @Input: - status (int or str): Pump operating mode, can be both int and string - - To get list of available modes: HeatCirculationPumpState.opstates() - """ - if status in HeatCirculationPumpState.__OPSTATES: - self._status = status - elif state in HeatCirculationPumpState.__OPSTATES_R: - self._status = HeatCirculationPumpState.__OPSTATES_R[status] - else: - raise AssertionError('HeatCirculationPumpState not recognized: \'{0}\''.format(mode)) - self._timestampMicros = timestampMicros - self._timePrecision = timePrecision - self._quality = quality - self._validity = validity - self._source = source - - - @staticmethod - def opstates(): - return HeatCirculationPumpState.__OPSTATES.copy() - - @property - def state(self): - return self._status - - @property - def stateAsString(self): - return HeatCirculationPumpState.__OPSTATES[self._status] - - def __repr__(self): - return "{0}(".format(self.__class__.__name__) + \ - "{0!r}, {1!r}, ".format(self._status, self._timestampMicros) + \ - "{0!r}, {1!r}, ".format(self._timePrecision, self._quality) + \ - "{0!r}, {1!r})".format(self._validity, self._source) - - - def __str__(self): - return 'HeatCirculationPumpState: {0} ({1})'.format(self.state, self.stateAsString) - - def parseToJSON(self): - from json import dumps - jsonObj = {} - jsonObj['state'] = { - 'status': self._status, - 'timestampMicros': self._timestampMicros, - 'timePrecision': self._timePrecision, - 'quality': self._quality, - 'validity': self._validity, - 'source': self._source, - } - return dumps(jsonObj) - - @staticmethod - def parseFromJSON(jsonString): - from json import JSONDecodeError, loads - if not type(jsonString) is str: raise TypeError('jsonString should be a string, found {0}'.format(type(jsonString))) - # result = None ## Appears unused - - try: - jsonObj = loads(jsonString).get('state') - return HeatCirculationPumpState( - jsonObj.get('status'), - jsonObj.get('timestampMicros'), - jsonObj.get('timePrecision'), - jsonObj.get('quality'), - jsonObj.get('validity'), - jsonObj.get('source')) - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(jsonString)) - raise e diff --git a/syslab-python/syslab/core/datatypes/Identifiers.py b/syslab-python/syslab/core/datatypes/Identifiers.py deleted file mode 100644 index bb7367b..0000000 --- a/syslab-python/syslab/core/datatypes/Identifiers.py +++ /dev/null @@ -1,73 +0,0 @@ -from dataclasses import dataclass -from . import CompositeMeasurement -from typing import Optional -# TODO: Add processing to these. - - -@dataclass -class DELV: - phaseAB: CompositeMeasurement - phaseBC: CompositeMeasurement - phaseCA: CompositeMeasurement - phaseAverage: CompositeMeasurement - - @staticmethod - def parseFromJSON(json_string): - from json import JSONDecodeError, loads - if not type(json_string) is str: - raise TypeError('jsonString should be a string, found {0}'.format(type(json_string))) - - try: - jsonObj = loads(json_string) - phaseABcm = CompositeMeasurement(**jsonObj.get('phaseAB')) - phaseBCcm = CompositeMeasurement(**jsonObj.get('phaseBC')) - phaseCAcm = CompositeMeasurement(**jsonObj.get('phaseCA')) - phaseAVGcm = CompositeMeasurement(**jsonObj.get('phaseAverage')) - return DELV(phaseABcm, phaseBCcm, phaseCAcm, phaseAVGcm) - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(json_string)) - raise e - - -class GPSL: - pass - - -class HLTH: - pass - - -class LNPL: - pass - - -class PNPL: - pass - - -@dataclass() -class WYEA: - phaseAB: CompositeMeasurement - phaseBC: CompositeMeasurement - phaseCA: CompositeMeasurement - neutral: Optional[CompositeMeasurement] = None - - @staticmethod - def parseFromJSON(json_string): - from json import JSONDecodeError, loads - if not type(json_string) is str: - raise TypeError('jsonString should be a string, found {0}'.format(type(json_string))) - - try: - jsonObj = loads(json_string) - phaseAcm = CompositeMeasurement(**jsonObj.get('phaseA')) - phaseBcm = CompositeMeasurement(**jsonObj.get('phaseB')) - phaseCcm = CompositeMeasurement(**jsonObj.get('phaseC')) - neutral = jsonObj.get('neutral') - if neutral is not None: - neutral = CompositeMeasurement(**neutral) - return WYEA(phaseAcm, phaseBcm, phaseCcm, neutral) - - except JSONDecodeError as e: - print('Not a valid JSON string: {0}.'.format(json_string)) - raise e diff --git a/syslab-python/syslab/core/datatypes/__init__.py b/syslab-python/syslab/core/datatypes/__init__.py deleted file mode 100644 index 56e0773..0000000 --- a/syslab-python/syslab/core/datatypes/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -__all__ = [] - -# Composite Data Types -from .CompositeBoolean import CompositeBoolean -from .CompositeMeasurement import CompositeMeasurement -from .CompositeStatus import CompositeStatus - -# SYSLAB-specific data types -from .Identifiers import DELV, GPSL, HLTH, LNPL, PNPL, WYEA - -# Unit-specific data types -from .BattOpMode import BattOpMode -from .FlowBatteryState import FlowBatteryState -from .HeatCirculationPumpMode import HeatCirculationPumpMode -from .HeatCirculationPumpState import HeatCirculationPumpState -from .ConverterTypes import ConvState, ConvOpMode diff --git a/syslab-python/syslab/get_flexhouse.py b/syslab-python/syslab/get_flexhouse.py deleted file mode 100644 index e4bd1d6..0000000 --- a/syslab-python/syslab/get_flexhouse.py +++ /dev/null @@ -1,27 +0,0 @@ -def get_flexhouse(simulated=False, physical=False, simulate_on_dumpload_ID="", simulate_on_battery=False): - """ - Return an instantiated object which operates as a flexhouse. - input: - simulated (bool): Whether the flexhouse should be simulated - physical (bool): Whether the flexhouse should be the real flexhouse - simulate_on_dumpload_ID (string): The ID of the dumpload on which to simulate the flexhouse - simulate_on_battery (bool): Whether to simulate on battery - - return: - flexhouse: A flexhouse object - """ - - if simulated: - if simulate_on_battery: - from .virtual.FlexHouse_sim_batt import FlexHouse_sim_batt - return FlexHouse_sim_batt('batt1') - else: - from .virtual.FlexHouse_sim import FlexHouse_sim - assert simulate_on_dumpload_ID != "", "Must supply an ID string for the dumpload used in Flexhouse simulation if not simulating on battery" - return FlexHouse_sim(simulate_on_dumpload_ID) - elif physical: - from .physical.FlexHouse_real import FlexHouse_real - return FlexHouse_real() - else: - raise Exception('Must define if FlexHouse instance is real or simulated') - diff --git a/syslab-python/syslab/physical/B2BConverter.py b/syslab-python/syslab/physical/B2BConverter.py deleted file mode 100644 index a2ca48e..0000000 --- a/syslab-python/syslab/physical/B2BConverter.py +++ /dev/null @@ -1,258 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit -from ..core.datatypes import CompositeMeasurement, CompositeBoolean, CompositeStatus -from ..core.datatypes import CommonDeviceConfig -from ..core.datatypes import DELV, WYEA, GPSL, PNPL, LNPL, HLTH, ConvOpMode, ConvState -from typing import List, Union -from time import time - - -def cast_to_cm(m: Union[CompositeMeasurement, float]): - if type(m) == float: - # TODO: Is there a better way to estimate precision of time.time? - request = CompositeMeasurement(m, timestampMicros=time()*1e6, timePrecision=1000) - elif type(m) == CompositeMeasurement: - request = m - else: - raise TypeError(f"Unknown request type: {type(m)}") - return request - - -class B2BConverter(SyslabUnit): - """ - Class covering back-to-back converters in SYSLAB. - - A full list of available switchboards can be found by calling 'SwitchBoard.getAvailableSwitchBoards()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - _CONVERTERS = { - 'ABBB2B': ('syslab-04.syslab.dk', '8080', 'B2BConverter'), - } - MAXP = 60 - MAXQ = 60 - - @staticmethod - def getAvailableUnits(): - return list(B2BConverter.__CONVERTERS.keys()) - - def __init__(self, which=None, host=None, port=None, unit_name=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_ABBConverter/ABBConverterWebService/{unit_name}/' - - super().__init__( - baseurl=baseurl, - which=which, - units=self._CONVERTERS, - host=host, - port=port, - unit_name=unit_name, - unit_type="B2BConverter") - - # Inventory functions - - # Configuration class used for HMI layout - def getNodeConfiguration(self, ) -> CommonDeviceConfig: - return self._request_resource('getNodeConfiguration') - - # Component description - def getConverterName(self, ) -> str: - return self._request_resource('getConverterName') - - def getConverterLogicalNameplate(self, ) -> LNPL: - raise NotImplementedError - - def getConverterPhysicalNameplate(self, ) -> PNPL: - raise NotImplementedError - - def getConverterHealth(self, ) -> HLTH: - raise NotImplementedError - - def getGPSLocation(self, ) -> GPSL: - raise NotImplementedError - - # Operating characteristics (corresponding to COPR/DRAT node) - def getRatedP(self, ) -> float: - raise NotImplementedError - # return self._request_resource('getRatedP') - - def getRatedS(self, ) -> float: - raise NotImplementedError - # return self._request_resource('getRatedS') - - def getRatedQ(self, ) -> float: - raise NotImplementedError - # return self._request_resource('getRatedQ') - - def getRatedU(self, ) -> float: - raise NotImplementedError - # return self._request_resource('getRatedU') - - def getRatedI(self, ) -> float: - raise NotImplementedError - # return self._request_resource('getRatedI') - - def getRatedf(self, ) -> float: - raise NotImplementedError - # return self._request_resource('getRatedf') - - # Operating mode settings (corresponding to DOPM node) - def getAvailableOperatingModes(self, ) -> List[ConvOpMode]: - raise NotImplementedError - - def getCurrentOperatingMode(self, ) -> ConvOpMode: - return self._request_resource('getCurrentOperatingMode') - - def setOperatingMode(self, mode: ConvOpMode) -> None: - raise NotImplementedError - - def isPSetpointEnabled(self, ) -> CompositeBoolean: - return self._request_resource('isPSetpointEnabled') - - def isQSetpointEnabled(self, ) -> CompositeBoolean: - return self._request_resource('isQSetpointEnabled') - - def isUSetpointEnabled(self, ) -> CompositeBoolean: - return self._request_resource('isUSetpointEnabled') - - def isfSetpointEnabled(self, ) -> CompositeBoolean: - return self._request_resource('isfSetpointEnabled') - - # Status information (corresponding to DPST node) - def getConverterStatus(self, ) -> ConvState: - return self._request_resource('getConverterStatus') - - # Alarms information - def hasActiveFault(self, ) -> CompositeBoolean: - raise NotImplementedError - - def hasActiveWarning(self, ) -> CompositeBoolean: - raise NotImplementedError - - def resetAlarms(self, ) -> None: - raise NotImplementedError - - def getActiveEventCode(self, ) -> CompositeStatus: - raise NotImplementedError - - # DER controller characteristics (corresponding to DRCT node) - def setActivePower(self, m: Union[CompositeMeasurement, float]) -> None: - """ - Send a request for the converter's output active power. Requires the converter to be in PQ mode. - - :param m: [kW] Requested active power. If a float, will be converted to a CompositeMeasurement with the current system time as timestamp.) - :return: None - """ - - P_UpperLimit = 15.0 - P_LowerLimit = -15.0 - - return self._request_resource('setActivePower', (), 'put', cast_to_cm(max(P_LowerLimit, min(m, P_UpperLimit))).parseToJSON()) - - def setFrequency(self, m: Union[CompositeMeasurement, float]) -> None: - """ - Send a request for the converter's output power. Requires the converter to be in UF mode. - - :param m: [Hz] Requested active power. If a float, will be converted to a CompositeMeasurement with the current system time as timestamp.) - :return: None - """ - return self._request_resource('seFrequency', (), 'put', cast_to_cm(m).parseToJSON()) - - def setReactivePower(self, m: Union[CompositeMeasurement, float]) -> None: - """ - Send a request for the converter's output reactive power. Requires the converter to be in PQ mode. - - :param m: [kVA] Requested active power. If a float, will be converted to a CompositeMeasurement with the current system time as timestamp.) - :return: None - """ - - Q_UpperLimit = 15.0 - Q_LowerLimit = -15.0 - - return self._request_resource('setReactivePower', (), 'put', cast_to_cm(max(Q_LowerLimit, min(m, Q_UpperLimit))).parseToJSON()) - - def setVoltage(self, m: Union[CompositeMeasurement, float]) -> None: - """ - Send a request for the converter's output voltage. Requires the converter to be in UF mode. - - :param m: [V] Requested active power. If a float, will be converted to a CompositeMeasurement with the current system time as timestamp.) - :return: None - """ - return self._request_resource('setVoltage', (), 'put', cast_to_cm(m).parseToJSON()) - - def getActivePowerSetpoint(self, ) -> CompositeMeasurement: - raise NotImplementedError - - def getFrequencySetpoint(self, ) -> CompositeMeasurement: - raise NotImplementedError - - def getReactivePowerSetpoint(self, ) -> CompositeMeasurement: - raise NotImplementedError - - def getVoltageSetpoint(self, ) -> CompositeMeasurement: - raise NotImplementedError - - # Synchronisation (corresponding to RSYN node) - def synchronize(self, ) -> None: - raise NotImplementedError - - def unsynchronize(self, ) -> None: - raise NotImplementedError - - def setDroopEnable(self, b: CompositeBoolean) -> None: - raise NotImplementedError - - def setLoadEnable(self, b: CompositeBoolean) -> None: - raise NotImplementedError - - def getVoltageDroopPct(self, ) -> CompositeMeasurement: - raise NotImplementedError - - def getFrequencyDroopPct(self, ) -> CompositeMeasurement: - raise NotImplementedError - - def setVoltageDroopPct(self, pct: CompositeMeasurement) -> None: - raise NotImplementedError - - def setFrequencyDroopPct(self, pct: CompositeMeasurement) -> None: - raise NotImplementedError - - # Reciprocating Engine (corresponds to DCIP node) - def startConverter(self, ) -> None: - return self._request_resource('startConverter', (), 'put') - - def softStopConverter(self, ) -> None: - return self._request_resource('softStopConverter', (), 'put') - - def stopConverter(self, ) -> None: - return self._request_resource('stopConverter', (), 'put') - - # AC quantities (corresponds to MMXU nodes) - def getActivePowerOutput(self, ) -> CompositeMeasurement: - return self._request_resource('getActivePowerOutput') - - def getReactivePowerOutput(self, ) -> CompositeMeasurement: - return self._request_resource('getReactivePowerOutput') - - def getOutputFrequency(self, ) -> CompositeMeasurement: - return self._request_resource('getOutputFrequency') - - def getOutputInterphaseVoltages(self, ) -> DELV: - return self._request_resource('getOutputInterphaseVoltages') - - def getOutputPhaseCurrents(self, ) -> WYEA: - raise NotImplementedError - - def getRectifierInterphaseVoltages(self, ) -> DELV: - return self._request_resource('getRectifierInterphaseVoltages') - - def getRectifierPhaseCurrents(self, ) -> WYEA: - return self._request_resource('getRectifierPhaseCurrents') - - def getSyncBusInterphaseVoltages(self, ) -> DELV: - raise NotImplementedError - - -class ABBB2BConverter(B2BConverter): - def __init__(self): - super(ABBB2BConverter, self).__init__(which='ABBB2B') diff --git a/syslab-python/syslab/physical/Battery.py b/syslab-python/syslab/physical/Battery.py deleted file mode 100644 index 1da016b..0000000 --- a/syslab-python/syslab/physical/Battery.py +++ /dev/null @@ -1,85 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit -from ..core.datatypes.FlowBatteryState import FlowBatteryState -from ..core.datatypes.BattOpMode import BattOpMode - -class Battery(SyslabUnit): - """The Battery class represents a battery in SYSLAB. - The Battery class is instantiated using a string with the unique name of the battery, ie. 'which' - - A full list of available batteries can be found by calling 'Battery.getAvailableBatteries()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - __BATTERIES = { - 'batt1': ('syslab-12.syslab.dk', '8080', 'batt1'), - 'battemu': ('syslab-31.syslab.dk', '8080', 'battemu'), - 'battfh1': ('syslab-s01.syslab.dk', '8080', 'battfh1'), - 'simlab-15': ('192.168.0.115', '8080', 'batt1'), - 'vbatt1': ('simlab-12', '8080', 'batt1'), - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_Battery/VRBBatteryWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__BATTERIES, - host=host, - port=port, - unit_name=unitname, - unit_type="Battery") - - def startBattery(self): - return self._request_resource('startBattery', (), 'put') - - def stopBattery(self): - return self._request_resource('stopBattery', (), 'put') - - def getActivePower(self): - return self._request_resource('getACActivePower') - - def setActivePower(self, setPoint): - - P_UpperLimit = 15.0 - P_LowerLimit = -15.0 - - return self._request_resource('setP', (max(P_LowerLimit, min(setPoint, P_UpperLimit))), 'put') - - def getReactivePower(self): - return self._request_resource('getACReactivePower') - - def setReactivePower(self, setPoint): - return self._request_resource('setQ', (setPoint), 'put') - - def getFrequency(self): - return self._request_resource('getACFrequency') - - def getRemainingFloodTime(self): - return min(self._request_resource('getRemainingFloodTime'), self._request_resource('getRemainingDrainTime')) - - def getCurrentOperatingMode(self): - return self._request_resource('getCurrentOperatingMode') - - def getCurrentOperatingState(self): - return self._request_resource('getCurrentOperatingState') - - def setOperatingMode(self, mode): - return self._request_resource('setOperatingMode', (), 'put', BattOpMode(mode).parseToJSON()) - - def getSOC(self): - return self._request_resource('getSOC') - - def getRatedActivePower(self): - return self._request_resource('getRatedP') - - def getRatedReactivePower(self): - return self._request_resource('getRatedQ') - - def getName(self): - return self._request_resource('getBatteryName') - - @staticmethod - def getAvailableBatteries(): - return list(Battery.__BATTERIES.keys()) diff --git a/syslab-python/syslab/physical/DieselGenerator.py b/syslab-python/syslab/physical/DieselGenerator.py deleted file mode 100644 index ef5b606..0000000 --- a/syslab-python/syslab/physical/DieselGenerator.py +++ /dev/null @@ -1,100 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit - - -class DieselGenerator(SyslabUnit): - """The DieselGenerator class represents a photovoltaic panel array in SYSLAB. - The DieselGenerator class is instantiated using a string with the unique name of the dumpload, ie. 'which' - - A full list of available panel arrays can be found by calling 'DieselGenerator.getAvailableDieselGenerator()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - __UNITS = { - 'diesel319': ('syslab-02.syslab.dk', '8080', 'genset1'), - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_Diesel/DEIFDieselGensetWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__UNITS, - host=host, - port=port, - unit_name=unitname, - unit_type="DieselGenerator") - - def getRatedP(self): - return self._request_resource('getRatedP') - - def getRatedQ(self): - return self._request_resource('getRatedQ') - - def getRatedS(self): - return self._request_resource('getRatedS') - - def getRatedU(self): - return self._request_resource('getRatedU') - - def getRatedf(self): - return self._request_resource('getRatedf') - - def isGeneratorBreakerClosed(self): - return self._request_resource('isGeneratorBreakerClosed') - - def isGensetRunning(self): - return self._request_resource('isGensetRunning') - - def isGensetSynchronized(self): - return self._request_resource('isGensetSynchronized') - - def isSynchronising(self): - return self._request_resource('isSynchronising') - - def closeGB(self): - return self._request_resource('closeGB', method='put') - - def openGB(self): - return self._request_resource('openGB', method='put') - - def startGenset(self): - return self._request_resource('startGenset', method='put') - - def stopGenset(self): - return self._request_resource('stopGenset', method='put') - - def setTargetActivePower(self, setpoint): - return self._request_resource('setTargetActivePower', setpoint, 'put') - - def setTargetReactivePower(self, setpoint): - return self._request_resource('setTargetReactivePower', setpoint, 'put') - - def getActivePower(self): - return self._request_resource('getActivePower') - - def getReactivePower(self): - return self._request_resource('getReactivePower') - - #TODO: Implement - def getCurrentGensetMode(self): - pass - - #TODO: Implement - def getCurrentRunningMode(self): - pass - - #TODO: Implement - def setGensetMode(self, mode): - pass - - #TODO: Implement - def setRunningMode(self, mode): - pass - - @staticmethod - def getAvailableDieselGenerators(): - return list(DieselGenerator.__UNITS.keys()) - - diff --git a/syslab-python/syslab/physical/Dumpload.py b/syslab-python/syslab/physical/Dumpload.py deleted file mode 100644 index dd67582..0000000 --- a/syslab-python/syslab/physical/Dumpload.py +++ /dev/null @@ -1,112 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit -import warnings - -class Dumpload(SyslabUnit): - """The Dumpload class represents a dumpload in SYSLAB. - The Dumpload class is instantiated using a string with the unique name of the dumpload, ie. 'which' - - A full list of available dumploads can be found by calling 'Dumpload.getAvailableDumpLoads()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - - __DUMPLOADS = { - 'mobload1': ('syslab-16.syslab.dk', '8080', 'mobload1'), - 'mobload2': ('syslab-17.syslab.dk', '8080', 'mobload2'), - 'mobload3': ('syslab-18.syslab.dk', '8080', 'mobload3'), - 'load1': ('syslab-05.syslab.dk', '8080', 'load1'), - 'vmobload1': ('simlab-16', '8080', 'mobload1'), - 'vmobload2': ('simlab-17', '8080', 'mobload2'), - 'vmobload3': ('simlab-18', '8080', 'mobload3'), - 'vload1': ('simlab-05', '8080', 'load1'), - 'simlab-05': ('192.168.0.105', '8080', 'mobload2'), - 'simlab-11': ('192.168.0.111', '8080', 'mobload1'), - 'simlab-12': ('192.168.0.112', '8080', 'load1'), - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_Load/GenericLoadWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__DUMPLOADS, - host=host, - port=port, - unit_name=unitname, - unit_type="Battery") - - def startLoad(self): - return self._request_resource('startLoad', (), 'put') - - def stopLoad(self): - return self._request_resource('stopLoad', (), 'put') - - def getPowerSetPoint(self): - return self._request_resource('getConstantP') - - def setPowerSetPoint(self, setPoint): - """ - Set the active power setpoint for the load. - - Inputs: - setPoint (float): Requested power setpoint - Outputs: - Ack (bool): Acknowledgement of receiver - """ - - P_UpperLimit = 15.0 - P_LowerLimit = 0 - - return self._request_resource('setConstantP', max(P_LowerLimit, min(setPoint, P_UpperLimit)), 'put') - - def getActivePower(self): - return self._request_resource('getActivePower') - - def getReactivePower(self): - """ - Get the reactive power draw from the load. - - Outputs: - Q (CompositeMeasurement): Current reactive power draw, calculated from active power draw (see note) - - NOTE: This is a theoretical value calculated from the relation - Q = Q_r * sin (pi * P /P_r) - where P_r and Q_r are the rated active and reactive power draw. - For control purposes, use the measured value from the switchboard - instead to get an actual measurement. - """ - warnings.warn("The output of getReactivePower from the Dumpload class is calculated from the active power draw rather than a measured value. For control purposes, use the measured power draw on the switchboard.") - return self._request_resource('getReactivePower') - - def getRatedPower(self): - return self._request_resource('getRatedP') - - def getRatedReactivePower(self): - return self._request_resource('getRatedQ') - - def getName(self): - return self._request_resource('getLoadName') - - def isLoadOn(self): - return self._request_resource('isLoadOn') - - @staticmethod - def getAvailableDumploads(): - return list(Dumpload.__DUMPLOADS.keys()) - - -class MobileLoad1(Dumpload): - def __init__(self): - super(MobileLoad1, self).__init__("mobload1") - - -class MobileLoad2(Dumpload): - def __init__(self): - super(MobileLoad2, self).__init__("mobload2") - - -class MobileLoad3(Dumpload): - def __init__(self): - super(MobileLoad3, self).__init__("mobload3") diff --git a/syslab-python/syslab/physical/EVSE.py b/syslab-python/syslab/physical/EVSE.py deleted file mode 100644 index bce38fa..0000000 --- a/syslab-python/syslab/physical/EVSE.py +++ /dev/null @@ -1,213 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit -from ..core.datatypes import CompositeMeasurement -from typing import Union -from time import time - -def cast_to_cm(m: Union[CompositeMeasurement, float]): - if type(m) == float: - # TODO: Is there a better way to estimate precision of time.time? - request = CompositeMeasurement(m, timestampMicros=time()*1e6, timePrecision=1000) - elif type(m) == CompositeMeasurement: - request = m - else: - raise TypeError(f"Unknown request type: {type(m)}") - return request - -class EVSE(SyslabUnit): - """The EVSE class represents a charging post in SYSLAB. - The EVSE class is instantiated using a string with the unique name of the charging post, ie. 'which' - - A full list of available charging posts can be found by calling 'EVSE.getAvailableChargingPosts()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - __CHARGINGPOSTS = { - 'V2G-319': ('syslab-35.syslab.dk', '8080', 'Endesa_V2G'), - 'EVSE-NEVIC-6': ('10.42.245.96', '8080', 'EVSE_NEVIC_6'), - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_EVSE/EVSEWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__CHARGINGPOSTS, - host=host, - port=port, - unit_name=unitname, - unit_type="EVSE") - - def isEVPresent(self): - return self._request_resource('isEVPresent') - - def canRemoteStartStop(self): - return self._request_resource('canRemoteStartStop') - - def canLimitChargePower(self): - return self._request_resource('canLimitChargePower') - - def canDischarge(self): - return self._request_resource('canDischarge') - - def hasSOC(self): - return self._request_resource('hasSOC') - - def hasACMeasurements(self): - return self._request_resource('hasACMeasurements') - - def hasDCMeasurements(self): - return self._request_resource('hasDCMeasurements') - - def getAvailableOperatingStates(self): - return self._request_resource('getAvailableOperatingStates') - - def getCurrentOperatingState(self): - return self._request_resource('getCurrentOperatingState') - - def getACActivePower(self): - return self._request_resource('getACActivePower') - - def getACReactivePower(self): - return self._request_resource('getACReactivePower') - - def getACFrequency(self): - return self._request_resource('getACFrequency') - - def getACVoltages(self): - return self._request_resource('getACVoltages') - - def getACCurrents(self): - return self._request_resource('getACCurrents') - - def getSOC(self): - return self._request_resource('getSOC') - - def getMinSOC(self): - return self._request_resource('getMinSOC') - - def getMaxSOC(self): - return self._request_resource('getMaxSOC') - - def startCharge(self): - return self._request_resource('startCharge', (), 'put') - - def stopCharge(self): - return self._request_resource('stopCharge', (), 'put') - - def startDischarge(self): - return self._request_resource('startDischarge', (), 'put') - - def stopDischarge(self): - return self._request_resource('stopDischarge', (), 'put') - - def getMinimumChargePower(self): - return self._request_resource('getMinimumChargePower') - - def getMaximumChargePower(self): - return self._request_resource('getMaximumChargePower') - - def getMinimumDischargePower(self): - return self._request_resource('getMinimumDischargePower') - - def getMaximumDischargePower(self): - return self._request_resource('getMaximumDischargePower') - - def setPowerSetpoint(self, setPoint): - - P_UpperLimit = 10.0 - P_LowerLimit = -10.0 - - return self._request_resource('setP', (), 'put', cast_to_cm(max(P_LowerLimit, min(setPoint, P_UpperLimit))).parseToJSON()) - - def isPSetpointEnabled(self): - return self._request_resource('isPSetpointEnabled') - - def getActiveEnergyImport(self): # TODO not working/implemented - return self._request_resource('getActiveEnergyImport') - - def getActiveEnergyExport(self): # TODO not working/implemented - return self._request_resource('getActiveEnergyExport') - - def getReactiveEnergyImport(self): # TODO not working/implemented - return self._request_resource('getReactiveEnergyImport') - - def getReactiveEnergyExport(self): # TODO not working/implemented - return self._request_resource('getReactiveEnergyExport') - - def getNodeConfiguration(self): # TODO not working/implemented - return self._request_resource('getNodeConfiguration') - - def getEVSEName(self): - return self._request_resource('getEVSEName') - - def getEVSELogicalNameplate(self): # TODO not working/implemented - return self._request_resource('getEVSELogicalNameplate') - - def getEVSEPhysicalNameplate(self): # TODO not working/implemented - return self._request_resource('getEVSEPhysicalNameplate') - - def getEVSEHealth(self): # TODO not working/implemented - return self._request_resource('getEVSEHealth') - - def getGPSLocation(self): # TODO not working/implemented - return self._request_resource('getGPSLocation') - - def getNumberOfEvents(self): # TODO not working/implemented - return self._request_resource('getNumberOfEvents') - - def getEvents(self): # TODO not working/implemented - return self._request_resource('getEvents') - - def getNumberOfAlarms(self): # TODO not working/implemented - return self._request_resource('getNumberOfAlarms') - - def getAlarms(self): # TODO not working/implemented - return self._request_resource('getAlarms') - - def getNumberOfUnacknowledgedAlarms(self): # TODO not working/implemented - return self._request_resource('getNumberOfUnacknowledgedAlarms') - - def getUnacknowledgedAlarms(self): # TODO not working/implemented - return self._request_resource('getUnacknowledgedAlarms') - - def acknowledgeAlarms(self): # TODO not working/implemented - return self._request_resource('acknowledgeAlarms') - - def getRatedP(self): - return self._request_resource('getRatedP') - - def getRatedQ(self): - return self._request_resource('getRatedQ') - - def getRatedS(self): - return self._request_resource('getRatedS') - - def getRatedU(self): - return self._request_resource('getRatedU') - - def getRatedf(self): - return self._request_resource('getRatedf') - - def getInverterName(self): # TODO not working/implemented - return self._request_resource('getInverterName') - - def getInverterLogicalNameplate(self): # TODO not working/implemented - return self._request_resource('getInverterLogicalNameplate') - - def getInverterHealth(self): # TODO not working/implemented - return self._request_resource('getInverterHealth') - - def getDCVoltage(self): # TODO not working/implemented - return self._request_resource('getDCVoltage') - - def getDCPower(self): # TODO not working/implemented - return self._request_resource('getDCPower') - - def isDCContactorClosed(self): # TODO not working/implemented - return self._request_resource('isDCContactorClosed') - - @staticmethod - def getAvailableEVSE(): - return list(EVSE.__CHARGINGPOSTS.keys()) diff --git a/syslab-python/syslab/physical/HeatSwitchBoard.py b/syslab-python/syslab/physical/HeatSwitchBoard.py deleted file mode 100644 index 6de8eb1..0000000 --- a/syslab-python/syslab/physical/HeatSwitchBoard.py +++ /dev/null @@ -1,164 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit -from ..core.datatypes import CompositeMeasurement, HeatCirculationPumpMode, HeatCirculationPumpState - - -class Valve: - """ - Convenience class which calls methods on its associated heatswitchboard - """ - def __init__(self, label, heatswitchboard): - self.label = label - self.heatswitchboard = heatswitchboard - #TODO: Add methods - -class Pump: - """ - Convenience class which calls methods on its associated heatswitchboard - """ - def __init__(self, label, heatswitchboard): - self.label = label - self.heatswitchboard = heatswitchboard - #TODO: Add methods - -class Meter: - """ - Convenience class which calls methods on its associated heatswitchboard - """ - def __init__(self, label, heatswitchboard): - self.label = label - self.heatswitchboard = heatswitchboard - #TODO: Add methods - - -class HeatSwitchBoard(SyslabUnit): - """ - The HeatSwitchBoard class represents a HeatSwitchBoard in SYSLAB. - The HeatSwitchBoard class is instantiated using a string with the unique name of the switchboard, ie. 'which' - - A full list of available switchboards can be found by calling 'SwitchBoard.getAvailableSwitchBoards()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - __HEAT_SWITCH_BOARDS = { - '716-h1': ('syslab-33.syslab.dk', '8080', '716-h1'), - } - - @staticmethod - def getAvailableHeatSwitchBoards(): - return list(HeatSwitchBoard.__HEAT_SWITCH_BOARDS.keys()) - - - def __init__(self, which=None, host=None, port=None, unitname=None): - - - baseurl = f'http://{host}:{port}/typebased_WebService_HeatSubstation/HeatSwitchboardWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__HEAT_SWITCH_BOARDS, - host=host, - port=port, - unit_name=unitname, - unit_type="HeatSwitchBoard") - - # Inventory functions - - #TODO Handle these in core/SYSLAB_unit.py by properly handling arrays. This is a bodge for now. - def getHeatMeters(self): - result = self._request_resource('getHeatMeters', check_types=False) - return result - - #TODO, P1: Awaiting Valve[] - def getValves(self): - raise NotImplementedError - - # Valve functions - - def getValvePosition(self, valve) -> CompositeMeasurement: - return self._request_resource('getValvePosition', valve) - - #TODO: Implement - #def setValvePosition(self, valve: str, position: float, timestamp=0): - def setValvePosition(self, valve: str, position: CompositeMeasurement): - """ - Sets *valve* to *position*. Position must be float in the - interval from 0.0 to 1.0 - Position = 0.0 => *valve* fully closed - Position = 1.0 => *valve* fully open - """ - assert 0.0 <= position.value and position.value <= 1.0 - return self._request_resource('setValvePosition', (valve), 'put', - position.parseToJSON()) - #CompositeMeasurement(value=position, timestampMicros=timestamp).parseToJSON()) - - # Meter functions - - def getBackTemperature(self, meter) -> CompositeMeasurement: - return self._request_resource('getBackTemperature', meter) - - def getFlow(self, meter) -> CompositeMeasurement: - return self._request_resource('getFlow', meter) - - def getThermalPower(self, meter) -> CompositeMeasurement: - return self._request_resource('getThermalPower', meter) - - def getFwdTemperature(self, meter) -> CompositeMeasurement: - return self._request_resource('getFwdTemperature', meter) - - def getPressure(self, meter) -> CompositeMeasurement: - return self._request_resource('getPressure', meter) - - def getVolume(self, meter) -> CompositeMeasurement: - return self._request_resource('getVolume', meter) - - def getMass(self, meter) -> CompositeMeasurement: - return self._request_resource('getMass', meter) - - def getHeatEnergy(self, meter) -> CompositeMeasurement: - return self._request_resource('getHeatEnergy', meter) - - def getCoolingEnergy(self, meter) -> CompositeMeasurement: - return self._request_resource('getCoolingEnergy', meter) - - # Pump functions - - def getPumpState(self, pump) -> HeatCirculationPumpState: - return self._request_resource('getPumpState', pump) - - def getPumpControlMode(self, pump) -> HeatCirculationPumpMode: - return self._request_resource('getPumpControlMode', pump) - - def setPumpControlMode(self, pump, mode: HeatCirculationPumpMode): - return self._request_resource('setPumpControlMode', (pump), 'put', mode.parseToJSON()) - - def setPumpMaxFlow(self, pump, limit: CompositeMeasurement): - return self._request_resource('setPumpMaxFlow', (pump), 'put', limit.parseToJSON()) - - def startPump(self, pump): - return self._request_resource('startPump', pump) - - def stopPump(self, pump): - return self._request_resource('stopPump', pump) - - #TODO: Split into three functions that check against current pump mode. - def setPumpSetpoint(self, pump, setpoint: CompositeMeasurement): - """ - Sets the target for the pump. - NOTE: How to interpret the setpoint depends on the mode which the pump is in. - Here be dragons. - """ - return self._request_resource('setPumpSetpoint', (pump), 'put', setpoint.parseToJSON()) - - def getPumpHead(self, pump) -> CompositeMeasurement: - return self._request_resource('getPumpHead', pump) - - def getPumpFlow(self, pump) -> CompositeMeasurement: - return self._request_resource('getPumpFlow', pump) - - def getPumpRPM(self, pump) -> CompositeMeasurement: - return self._request_resource('getPumpRPM', pump) - - def getPumpRelPerformance(self, pump) -> CompositeMeasurement: - return self._request_resource('getPumpPerformance', pump) - diff --git a/syslab-python/syslab/physical/MeteoMast.py b/syslab-python/syslab/physical/MeteoMast.py deleted file mode 100644 index 87d80b4..0000000 --- a/syslab-python/syslab/physical/MeteoMast.py +++ /dev/null @@ -1,72 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit - - -class MeteoMast(SyslabUnit): - __METMASTS = { - 'metmast1': ('syslab-13.syslab.dk', '8080', 'meteo1'), - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_Meteo/MeteoStationWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__METMASTS, - host=host, - port=port, - unit_name=unitname, - unit_type="MeteoMast") - - - - def getAirPressure(self, instrumentIndex: int or str): - if type(instrumentIndex) is str: - return self._request_resource('getAirPressure2', instrumentIndex) - if type(instrumentIndex) is int: - return self._request_resource('getAirPressure1', instrumentIndex) - - def getAirTemperature(self, instrumentIndex: int or str): - if type(instrumentIndex) is str: - return self._request_resource('getAirTemperature2', instrumentIndex) - if type(instrumentIndex) is int: - return self._request_resource('getAirTemperature1', instrumentIndex) - - def getHeightAboveGround(self): - return self._request_resource('getHeightAboveGround') - - def getInsolation(self, instrumentIndex: int or str): - if type(instrumentIndex) is str: - return self._request_resource('getInsolation2', instrumentIndex) - if type(instrumentIndex) is int: - return self._request_resource('getInsolation1', instrumentIndex) - - def getMeteoGPSLocation(self): - return self._request_resource('getMeteoGPSLocation') - - def getRelativeHumidity(self, instrumentIndex: int or str): - if type(instrumentIndex) is str: - return self._request_resource('getRelativeHumidity2', instrumentIndex) - if type(instrumentIndex) is int: - return self._request_resource('getRelativeHumidity1', instrumentIndex) - - def getWindDirection(self, instrumentIndex: int or str): - if type(instrumentIndex) is str: - return self._request_resource('getWindDirection2', instrumentIndex) - if type(instrumentIndex) is int: - return self._request_resource('getWindDirection1', instrumentIndex) - - def getWindSpeed(self, instrumentIndex: int or str): - if type(instrumentIndex) is str: - return self._request_resource('getWindSpeed2', instrumentIndex) - if type(instrumentIndex) is int: - return self._request_resource('getWindSpeed1', instrumentIndex) - - def getInstrumentNames(self): - return self._request_resource('getInstrumentNames') - - def getSupportedInstrumentTypes(self): - return self._request_resource('getSupportedInstrumentTypes') - - def getInstrumentNamesForType(self, instrumentType: str): - return self._request_resource('getInstrumentNamesForType', instrumentType) diff --git a/syslab-python/syslab/physical/Photovoltaics.py b/syslab-python/syslab/physical/Photovoltaics.py deleted file mode 100644 index 2915c78..0000000 --- a/syslab-python/syslab/physical/Photovoltaics.py +++ /dev/null @@ -1,61 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit - - -class Photovoltaics(SyslabUnit): - """The Photovoltaics class represents a photovoltaic panel array in SYSLAB. - The Photovoltaics class is instantiated using a string with the unique name of the dumpload, ie. 'which' - - A full list of available panel arrays can be found by calling 'Photovoltaics.getAvailablePhotovoltaics()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - __PHOTOVOLTAICS = { - 'pv319': ('syslab-24.syslab.dk', '8080', 'pv319'), - 'pv715': ('syslab-10.syslab.dk', '8080', 'pv715'), - 'pv117': ('syslab-07.syslab.dk', '8080', 'pv117'), - 'simlab-03': ('192.168.0.103', '8080', 'pv715'), - 'simlab-13': ('192.168.0.113', '8080', 'pv319'), - 'vpv319': ('simlab-24', '8080', 'pv319'), - 'vpv715': ('simlab-10', '8080', 'pv715'), - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_PV/PVSystemWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__PHOTOVOLTAICS, - host=host, - port=port, - unit_name=unitname, - unit_type="Photovoltaics") - - def getACActivePower(self): - return self._request_resource('getACActivePower') - - def getACReactivePower(self): - return self._request_resource('getACReactivePower') - - def getPacLimit(self): - return self._request_resource('getPacLimit') - - def getQSetpoint(self): - return self._request_resource('getQSetpoint') - - def getRatedPower(self): - return self._request_resource('getRatedP') - - def getName(self): - return self._request_resource('getSystemName') - - def setPacLimit(self, setPoint): - return self._request_resource('setPacLimit', setPoint, 'put') - - def setQSetpoint(self, Q): - return self._request_resource('setQ', Q, 'put') - - @staticmethod - def getAvailablePhotovoltaics(): - return list(Photovoltaics.__PHOTOVOLTAICS.keys()) diff --git a/syslab-python/syslab/physical/SwitchBoard.py b/syslab-python/syslab/physical/SwitchBoard.py deleted file mode 100644 index 383fc79..0000000 --- a/syslab-python/syslab/physical/SwitchBoard.py +++ /dev/null @@ -1,144 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit - - -class SwitchBoard(SyslabUnit): - """ - The SwitchBoard class represents a SwitchBoard in SYSLAB. - The SwitchBoard class is instantiated using a string with the unique name of the switchboard, ie. 'which' - - A full list of available switchboards can be found by calling 'SwitchBoard.getAvailableSwitchBoards()' - - Alternatively, the user may specify a host and port to connect to via the *host* and *port* arguments. - """ - - __SWITCH_BOARDS = { - '319-2':('syslab-01.syslab.dk', '8080', '319-2'), - '319-3':('syslab-52.syslab.dk', '8080', '319-3'), - '117-2':('syslab-11.syslab.dk', '8080', '117-2'), - '117-4':('syslab-11.syslab.dk', '8080', '117-4'), - '117-5':('syslab-11.syslab.dk', '8080', '117-5'), - '117-6':('syslab-26.syslab.dk', '8080', '117-6'), - '715-2':('syslab-09.syslab.dk', '8080', '715-2'), - '716-2':('syslab-29.syslab.dk', '8080', '716-2'), - 'simlab-00': ('192.168.0.1', '8080', '319-2'), - 'simlab-10': ('192.168.0.2', '8080', '319-2'), - 'simlab-20': ('192.168.0.3', '8080', '319-2'), - 'vswitchboard': ('simlab-01', '8080', '319-2') - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_Substation/StandardSubstationWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__SWITCH_BOARDS, - host=host, - port=port, - unit_name=unitname, - unit_type="SwitchBoard") - - def getName(self): - return self._request_resource('getSwitchboardName') - - def getActivePower(self, instrName): - return self._request_resource('getActivePower', instrName) - - def getPhaseActivePower(self, instrName): - return self._request_resource('getPhaseActivePower', instrName) - - def getReactivePower(self, instrName): - return self._request_resource('getReactivePower', instrName) - - def getPhaseReactivePower(self, instrName): - return self._request_resource('getPhaseReactivePower', instrName) - - def getApparentPower(self, instrName): - return self._request_resource('getApparentPower', instrName) - - def getPhaseApparentPower(self, instrName): - return self._request_resource('getPhaseApparentPower', instrName) - - def getPowerFactor(self, instrName): - return self._request_resource('getPowerFactor', instrName) - - def getPhasePowerFactor(self, instrName): - return self._request_resource('getPhasePowerFactor', instrName) - - def getActiveEnergyExport(self, instrName): - return self._request_resource('getActiveEnergyExport', instrName) - - def getActiveEnergyImport(self, instrName): - return self._request_resource('getActiveEnergyImport', instrName) - - def getReactiveEnergyExport(self, instrName): - return self._request_resource('getReactiveEnergyExport', instrName) - - def getReactiveEnergyImport(self, instrName): - return self._request_resource('getReactiveEnergyImport', instrName) - - def isAuthenticated(self): - return self._request_resource('isAuthenticated') - - def getBreakerState(self, breakerName): - return self._request_resource('getBreakerState', breakerName) - - def getFrequency(self, instrName): - return self._request_resource('getFrequency', instrName) - - def getBayNames(self): - return self._request_resource('getBayNames') - - def getBreakerName(self, busbarName, bayName): - return self._request_resource('getBreakerName', (busbarName, bayName)) - - def getInstrumentNames(self, bayName): - return self._request_resource('getInstrumentNamesPerBay', bayName) - - def getBusbarNames(self): - return self._request_resource('getBusbarNames') - - def getInterphaseVoltage(self, instrName): - return self._request_resource('getInterphaseVoltage', instrName) - - def getInterphaseVoltages(self, instrName): - return self._request_resource('getInterphaseVoltages', instrName) - - def getPhaseVoltage(self, instrName): - return self._request_resource('getPhaseVoltage', instrName) - - def getPhaseVoltages(self, instrName): - return self._request_resource('getPhaseVoltages', instrName) - - def getVoltageImbalance(self, instrName): - return self._request_resource('getVoltageImbalance', instrName) - - def getPhaseCurrent(self, instrName): - return self._request_resource('getPhaseCurrent', instrName) - - def getNeutralCurrent(self, instrName): - return self._request_resource('getNeutralCurrent', instrName) - - def getPhaseCurrents(self, instrName): - return self._request_resource('getPhaseCurrents', instrName) - - def getCurrentImbalance(self, instrName): - return self._request_resource('getCurrentImbalance', instrName) - - def authenticate(self, user, password): - return self._request_resource('authenticate', (user, password), 'put') - - def logout(self): - return self._request_resource('logout', (), 'put') - - def closeBreaker(self, breakerName): - return self._request_resource('closeBreaker', breakerName, 'put') - - def openBreaker(self, breakerName): - return self._request_resource('openBreaker', (breakerName), 'put') - - @staticmethod - def getAvailableSwitchBoards(): - return list(SwitchBoard.__SWITCH_BOARDS.keys()) - - diff --git a/syslab-python/syslab/physical/WindTurbine.py b/syslab-python/syslab/physical/WindTurbine.py deleted file mode 100644 index 64c8f33..0000000 --- a/syslab-python/syslab/physical/WindTurbine.py +++ /dev/null @@ -1,36 +0,0 @@ -from ..core.SyslabUnit import SyslabUnit - - -class WindTurbine(SyslabUnit): - __TURBINES = { - 'gaia1': ('syslab-03.syslab.dk', '8080', 'gaia1'), - 'simlab-01': ('192.168.0.101', '8080', 'gaia1'), - 'vgaia1': ('simlab-03', '8080', 'gaia1'), - } - - def __init__(self, which=None, host=None, port=None, unitname=None): - - baseurl = 'http://{host}:{port}/typebased_WebService_WTGS/GaiaWindTurbineWebService/{unit_name}/' - super().__init__( - baseurl=baseurl, - which=which, - units=self.__TURBINES, - host=host, - port=port, - unit_name=unitname, - unit_type="WindTurbine") - - def getGeneratorName(self): - return self._request_resource('getGeneratorName') - - def getName(self): - return self.getGeneratorName() - - def getActivePower(self): - return self._request_resource('getActivePower') - - def getReactivePower(self): - return self._request_resource('getReactivePower') - - def getWindspeed(self): - return self._request_resource('getWindspeedOutsideNacelle') diff --git a/syslab-python/syslab/physical/__init__.py b/syslab-python/syslab/physical/__init__.py deleted file mode 100644 index e663243..0000000 --- a/syslab-python/syslab/physical/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from .Battery import Battery -from .DieselGenerator import DieselGenerator -from .Dumpload import Dumpload -from .HeatSwitchBoard import HeatSwitchBoard -from .MeteoMast import MeteoMast -from .Photovoltaics import Photovoltaics -from .SwitchBoard import SwitchBoard -from .WindTurbine import WindTurbine -from .B2BConverter import B2BConverter -from .EVSE import EVSE diff --git a/syslab-python/syslab/virtual/FlexHouse_real.py b/syslab-python/syslab/virtual/FlexHouse_real.py deleted file mode 100644 index 25fb997..0000000 --- a/syslab-python/syslab/virtual/FlexHouse_real.py +++ /dev/null @@ -1,47 +0,0 @@ -class FlexHouse_real(): - def __init__(self): - pass - - def setActivePower(self, power_reference): - if power_reference < -10: - power_reference = -10 - - if power_reference > 0: - raise ValueError("Positive power means production") - self.__setValue('flexHousePowerRef_kW',-power_reference) - - def getTemperature(self): - return self.__getValue('flexHouseTemperature_C') - - def getActivePower(self): - return self.__getValue('flexHousePower_kW') - - def __getValue(self, key): - from requests import get, auth - import re - - if not type(key) is str: raise TypeError('Key should be a string, found {0}'.format(type(key))) - if key is '': raise TypeError('Key should be an empty string') - - url = 'http://whiteboard.syslab.dk/wbget.php' - r = get(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - entries = r.text.split('\n') - - result = None - - for entry in entries: - entry = entry.rstrip().lstrip() - g = re.match('SYSLAB@(\d+):{0}=(.+);'.format(key), entry) - if g is None: - continue - else: - g = g.groups() - result = g[1] - break - - return result - - def __setValue(selv, key, value): - from requests import post, auth - url = '{0}{1}?source=SYSLAB&{2}={3}'.format('http://whiteboard.syslab.dk/', 'wbset.php', key, str(value)) - post(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) \ No newline at end of file diff --git a/syslab-python/syslab/virtual/FlexHouse_sim.py b/syslab-python/syslab/virtual/FlexHouse_sim.py deleted file mode 100644 index 3b0720d..0000000 --- a/syslab-python/syslab/virtual/FlexHouse_sim.py +++ /dev/null @@ -1,51 +0,0 @@ -from ..physical.Dumpload import Dumpload -from ..virtual.MetMast import MetMast -from datetime import datetime - -class FlexHouse_sim(Dumpload): - def __init__(self, which='localhost'): - super().__init__(which) - self.internal_temperature = 20 # Celsius - self.time = datetime.now() - self.mt = MetMast() - - # The variables below are only relevant for implementing an advanced house model. - #self.__Th = 20 # internal heater state - #self.__Te = 19 # envelope state - #self.__Aw = 14.351 # m^2 - #self.__Ce = 4.741 # kWh/C - #self.__Ch = 0.00225 # kWh/Cst - #self.__Ci = 2.555 # kWh/C - #self.__Rea = 3.265 # C/kW - #self.__Rie = 0.817 # C/kW - #self.__Ria = 37.005 # C/kW - #self.__Rih = 140.44 # C/kW - - def setPowerConsumption(self, power_reference): - if power_reference > 10: - self.startLoad() - power_reference = 10.0 - if power_reference < 0: - raise ValueError("Negative power means production") - if power_reference == 0: - self.stopLoad() - self.setPowerSetPoint(power_reference) - - def step_sim(self): - time_now = datetime.now() - time_delta = (time_now - self.time).total_seconds() - T_ambient = self.mt.getTemperature() - irradiance = self.mt.getInsolation()/1000 - - # Below is a simple house model. A more complex one can be implemented - self.internal_temperature += 0.5*(self.getActivePower().value/3600*time_delta) - 0.00025*((self.internal_temperature-T_ambient)*time_delta) + 0.001*irradiance*time_delta - #self.__Th = 20 # internal heater state - #self.__Te = 19 # envelope state - self.time = time_now - - def getTemperature(self): - self.step_sim() - return self.internal_temperature - - - diff --git a/syslab-python/syslab/virtual/FlexHouse_sim_batt.py b/syslab-python/syslab/virtual/FlexHouse_sim_batt.py deleted file mode 100644 index b1ce14b..0000000 --- a/syslab-python/syslab/virtual/FlexHouse_sim_batt.py +++ /dev/null @@ -1,52 +0,0 @@ -from ..physical.Battery import Battery -from datetime import datetime - - -class FlexHouse_sim_batt(Battery): - def __init__(self, which='localhost'): - super().__init__(which) - self.internal_temperature = 20 # Celsius - self.time = datetime.now() - self.loss = 1 # kW - if self.getRemainingFloodTime() == 300: - #print('Battery is not started. I will initiate start sequence, please retry in 5 minutes') - self.startBattery() - raise SystemError('Battery is not started. I will initiate start sequence, please retry in 5 minutes') - if (self.getRemainingFloodTime() > 1) and (self.getRemainingFloodTime() < 300): - #print('Battery is not ready yet') - raise SystemError('Battery is not ready yet, please wait {} seconds'.format(self.getRemainingFloodTime())) - - # The variables below are only relevant for implementing and advanced house model. - #self.__Th = 20 # internal heater state - #self.__Te = 19 # envelope state - #self.__Aw = 14.351 # m^2 - #self.__Ce = 4.741 # kWh/C - #self.__Ch = 0.00225 # kWh/C - #self.__Ci = 2.555 # kWh/C - #self.__Rea = 3.265 # C/kW - #self.__Rie = 0.817 # C/kW - #self.__Ria = 37.005 # C/kW - #self.__Rih = 140.44 # C/kW - - def setPowerConsumption(self, power_reference): - if power_reference > 10: - power_reference = 10 - if power_reference < 0: - raise ValueError("Negative power means production") - self.setActivePower(power_reference) - - def step_sim(self): - time_now = datetime.now() - time_delta = (time_now - self.time).total_seconds() - # Below is a simple house model. A more complex one can be implemented - self.internal_temperature += 0.5*(self.getActivePower().value/3600*time_delta) - 2*(self.loss/3600*time_delta) - #self.__Th = 20 # internal heater state - #self.__Te = 19 # envelope state - self.time = time_now - - def getTemperature(self): - self.step_sim() - return self.internal_temperature - - - diff --git a/syslab-python/syslab/virtual/MetMast_wb.py b/syslab-python/syslab/virtual/MetMast_wb.py deleted file mode 100644 index 8389c17..0000000 --- a/syslab-python/syslab/virtual/MetMast_wb.py +++ /dev/null @@ -1,40 +0,0 @@ -class MetMast(): - def __init__(self): - pass - - def getTemperature(self): - return self.__getValue('OutsideTemperature') - - def getInsolation(self): - return self.__getValue('Insolation') - - def getWindDirection(self): - return self.__getValue('WindDirection') - - def getWindSpeed(self): - return self.__getValue('WindSpeed') - - def __getValue(self, key): - from requests import get, auth - import re - - if not type(key) is str: raise TypeError('Key should be a string, found {0}'.format(type(key))) - assert key is not '', 'Key should not be an empty string' - - url = 'http://whiteboard.syslab.dk/wbget.php' - r = get(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - entries = r.text.split('\n') - - result = None - - for entry in entries: - entry = entry.rstrip().lstrip() - g = re.match('SYSLAB@(\d+):{0}=(.+);'.format(key), entry) - if g is None: - continue - else: - g = g.groups() - result = g[1] - break - - return result diff --git a/syslab-python/syslab/virtual/WaterBoiler.py b/syslab-python/syslab/virtual/WaterBoiler.py deleted file mode 100644 index 1ef630e..0000000 --- a/syslab-python/syslab/virtual/WaterBoiler.py +++ /dev/null @@ -1,28 +0,0 @@ -from ..physical.Dumpload import Dumpload -from datetime import datetime - - -class WaterBoiler(Dumpload): - - def __init__(self, which='localhost'): - super().__init__(which) - - self.energy_state = 10 # kWh - self.energy_max = 15 - self.time = datetime.now() - self.loss = 1 # kW - - def step_sim(self): - time_now = datetime.now() - time_delta = (time_now - self.time).total_seconds() - power = self.getActivePower().value - self.energy_state += (power - self.loss)/3600*time_delta - self.time = time_now - - def getSOC(self): - self.step_sim() - if self.energy_state > self.energy_max: - self.energy_state = self.energy_max - elif self.energy_state < 0: - self.energy_state = 0.0 - return self.energy_state diff --git a/syslab-python/syslab/virtual/__init__.py b/syslab-python/syslab/virtual/__init__.py deleted file mode 100644 index 1e136c6..0000000 --- a/syslab-python/syslab/virtual/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import * diff --git a/syslab-python/syslab/whiteboard/CommModule.py b/syslab-python/syslab/whiteboard/CommModule.py deleted file mode 100644 index 16f5096..0000000 --- a/syslab-python/syslab/whiteboard/CommModule.py +++ /dev/null @@ -1,143 +0,0 @@ -from syslab.whiteboard.WhiteBoardEntry import WhiteBoardEntry - -class CommModule(): - __BASE_URL = 'http://whiteboard.syslab.dk/' - - def __init__(self, namespace): - if not type(namespace) is str or len(namespace) == 0: raise TypeError('Namespace should be an non-empty string, found "{0}"'.format(type(namespace))) - - self.__namespace = namespace - self.__entries = {} - - def appendValue(self, key, value): - values = self.getList(key) - - if values == None: - self.publishToWhiteBoardServer(key, '[{0}]'.format(str(value))) - else: - values.append(value) - self.publishList(key, values) - - def getList(self, key): - from ast import literal_eval - if not type(key) is str: raise TypeError('Key should be a string, found {0}'.format(type(key))) - - entry = self.getFromWhiteBoardServer(key) - - values = None - if entry is not None: - values_str = str(entry.value) - values_str = values_str.replace('[','["').replace(']','"]'.replace(',','","')) - values = literal_eval(values_str) - if type(values) is not list: - values = [values, ] - return values - - def getAllEntries(self): - return self.__entries - - def update(self): - from requests import get, auth - import re - - url = CommModule.__BASE_URL + 'wbget.php' - r = get(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - entries = r.text.split('\n') - - result = {} - for entry in entries: - entry = entry.rstrip().lstrip() - g = re.match('SYSLAB@(\d+):{0}::(\w+)=(.+);'.format(self.__namespace), entry) - if g is None: - continue - else: - g = g.groups() - self.__entries[g[1]] = WhiteBoardEntry(g[1], g[2], g[0]) - - def printEntries(self): - if len(self.__entries)==0: - print('No WhiteBoard entries found for namespace: {0}'.format(self.__namespace)) - return - - for e in self.__entries: - print(e) - - def publishList(self, key, values): - from requests import post, auth - if not type(key) is str: raise TypeError('Key should be a string, found {0}'.format(type(key))) - if not type(values) is list: raise TypeError('Values should be represented by a list'.format(type(values))) - - values_str = "[{0}]".format(",".join(map(str,values))) - - url = '{0}{1}?source=SYSLAB&{2}::{3}={4}'.format(CommModule.__BASE_URL, 'wbset.php', self.__namespace, str(key), values_str) - post(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - - def getFromWhiteBoardServer(self, key): - """ - Go in and read/write the value from a key from the whiteboard. The value - should use decimal dot, not comma! - """ - from requests import get, auth - import re - - if not type(key) is str: raise TypeError('Key should be a string, found {0}'.format(type(key))) - if key is '': raise TypeError('Key should be an empty string') - - url = CommModule.__BASE_URL+'wbget.php' - r = get(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - entries = r.text.split('\n') - - result = None - - for entry in entries: - entry = entry.rstrip().lstrip() - g = re.match('SYSLAB@(\d+):{0}::{1}=(.+);'.format(self.__namespace, key), entry) - if g is None: - continue - else: - g = g.groups() - result = WhiteBoardEntry(key, g[1], g[0]) - break - - return result - - def publishToWhiteBoardServer(self, key, value): - from requests import post, auth - if not type(key) is str: raise TypeError('Key should be a string, found {0}'.format(type(key))) - if type(value) is list or type(value) is dict or type(value) is tuple: raise TypeError('This function only supports single values, found {0}'.format(type(value))) - - url = '{0}{1}?source=SYSLAB&{2}::{3}={4}'.format(CommModule.__BASE_URL, 'wbset.php', self.__namespace, str(key), str(value)) - post(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - - def getPoolKeys(self): - from requests import get, auth - import re - - url = CommModule.__BASE_URL+'wbget.php' - r = get(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - entries = r.text.split('\n') - - result = {} - for entry in entries: - entry = entry.rstrip().lstrip() - g = re.match('SYSLAB@(\d+):{0}::(\w+)=(.+)'.format(self.__namespace), entry) - if g is None: - continue - else: - g = g.groups() - result[g[1]] = g[2] - - return result - - def clearKey(self, key): - from requests import post, auth - if not type(key) is str: raise TypeError('Key should be a string, found {0}'.format(type(key))) - - url = '{0}{1}?source=SYSLAB&key={2}::{3}'.format(CommModule.__BASE_URL, 'wbclean.php', self.__namespace, str(key)) - post(url, auth=auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - - def clearAllKeys(self): - entries = self.getPoolKeys() - - for key in entries.keys(): - self.clearKey(key) diff --git a/syslab-python/syslab/whiteboard/WhiteBoardEntry.py b/syslab-python/syslab/whiteboard/WhiteBoardEntry.py deleted file mode 100644 index 54587a3..0000000 --- a/syslab-python/syslab/whiteboard/WhiteBoardEntry.py +++ /dev/null @@ -1,21 +0,0 @@ -class WhiteBoardEntry: - def __init__(self, key, value, time): - self.__key = key - self.__value = value - self.__time = int(time) - - @property - def key(self): - return self.__key - - @property - def value(self): - return self.__value - - @property - def time(self): - return self.__time - - def __str__(self): - from datetime import datetime - return 'WhiteBoardEntry: {0} -> {1} (@time: {2})'.format(self.key, self.value, datetime.fromtimestamp(self.time)) diff --git a/syslab-python/syslab/whiteboard/Whiteboard.py b/syslab-python/syslab/whiteboard/Whiteboard.py deleted file mode 100644 index 24a2347..0000000 --- a/syslab-python/syslab/whiteboard/Whiteboard.py +++ /dev/null @@ -1,23 +0,0 @@ -from bs4 import BeautifulSoup -import requests - -def getFromWhiteBoardServer(key): - """ - Go in and read/write the value from a key from the whiteboard. The value - should use decimal dot, not comma! - """ - - url = 'http://whiteboard.syslab.dk/wbget.php?mode=html' - r = requests.get(url, auth=requests.auth.HTTPBasicAuth('twinPV99', 'twinPV99')) - data = r.text - print(data) - soup = BeautifulSoup(data) - table = soup.find('table') - key = table.find('td', text=key) - value = key.findNext('td') - return value.text - - -def publishToWhiteBoardServer(key, value): - url = 'http://whiteboard.syslab.dk/wbset.php?source=SYSLAB&' + key + '=' + str(value) - r = requests.post(url, auth=requests.auth.HTTPBasicAuth('twinPV99', 'twinPV99')) diff --git a/syslab-python/syslab/whiteboard/__init__.py b/syslab-python/syslab/whiteboard/__init__.py deleted file mode 100644 index 3a95699..0000000 --- a/syslab-python/syslab/whiteboard/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .CommModule import CommModule -from .WhiteBoardEntry import WhiteBoardEntry -from .Whiteboard import publishToWhiteBoardServer, getFromWhiteBoardServer diff --git a/syslab-python/syslab_ctrl_log_SP_1687041679.json b/syslab-python/syslab_ctrl_log_SP_1687041679.json deleted file mode 100644 index e69de29..0000000 diff --git a/syslab-python/tests/__init__.py b/syslab-python/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/syslab-python/tests/runall.py b/syslab-python/tests/runall.py deleted file mode 100644 index e69de29..0000000 diff --git a/util.py b/util.py deleted file mode 100644 index 321e0e9..0000000 --- a/util.py +++ /dev/null @@ -1,5 +0,0 @@ -def clamp(a, x, b): - """ - Restrict x to lie in the range [a, b] - """ - return max(a, min(x, b))