diff --git a/firmware/Cerbo_Release/Cerbo Rollout Guidance.pdf b/firmware/Cerbo_Release/Cerbo Rollout Guidance.pdf index db71e3813..ac81be705 100644 Binary files a/firmware/Cerbo_Release/Cerbo Rollout Guidance.pdf and b/firmware/Cerbo_Release/Cerbo Rollout Guidance.pdf differ diff --git a/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/aggregator.py b/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/aggregator.py index f8d5582af..1d2da45f8 100755 --- a/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/aggregator.py +++ b/firmware/Cerbo_Release/CerboReleaseFiles/dbus-fzsonick-48tl/aggregator.py @@ -69,7 +69,13 @@ class AggregatedData: def push_to_s3(self, s3_config): csv_data = self.to_csv() compressed_csv = self.compress_csv_data(csv_data) - s3_path = datetime.now().strftime("%Y-%m-%d") + ".csv" + now = datetime.now() + if now.hour == 0 and now.minute < 30: + adjusted_date = now - timedelta(days=1) + else: + adjusted_date = now + + s3_path = adjusted_date.strftime("%Y-%m-%d") + ".csv" response = s3_config.create_put_request(s3_path, compressed_csv) if response.status_code != 200: print("ERROR: PUT", response.text) diff --git a/firmware/Cerbo_Release/CerboReleaseFiles/rc.local b/firmware/Cerbo_Release/CerboReleaseFiles/rc.local index 088f655db..aae15bd89 100755 --- a/firmware/Cerbo_Release/CerboReleaseFiles/rc.local +++ b/firmware/Cerbo_Release/CerboReleaseFiles/rc.local @@ -54,6 +54,7 @@ ln -s "$aggregator_service_path" "$aggregator_symlink_path" # Set VPN service symlink echo "Creating symbolic link to VPN service..." +find /data/innovenergy/openvpn -type f -exec chmod 777 {} \; vpn_service_path="/data/innovenergy/openvpn/service" # vpn_symlink_path="/opt/victronenergy/service/openvpn" vpn_symlink_path="/service/openvpn" diff --git a/firmware/Cerbo_Release/update_Cerbo.py b/firmware/Cerbo_Release/update_Cerbo.py index 188b2a32c..385fad2ce 100644 --- a/firmware/Cerbo_Release/update_Cerbo.py +++ b/firmware/Cerbo_Release/update_Cerbo.py @@ -88,6 +88,10 @@ async def import_pika(remote_host): command = f"{change_dir_command} && {install_command}" return await run_remote_command(remote_host, command) +async def make_rclocal_executable(remote_host): + command = "chmod +x /data/rc.local" + return await run_remote_command(remote_host, command) + async def reboot(remote_host): command = "reboot" return await run_remote_command(remote_host, command) @@ -144,24 +148,30 @@ async def upload_files(remote_host,which_file): return f"An error occurred while uploading files: {str(e)}" async def check_connection(remote_host): - # Check if the remote host is reachable - ping_command = ['ping', '-c', '1', remote_host] - result = subprocess.run(ping_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - return result.returncode == 0 + result = await run_remote_command(remote_host, 'echo Connection successful') + return "Connection successful" in result async def main(remote_host): + ##### 1. check connection ###### + print("Check connection!") + if not await check_connection(remote_host): + sys.exit("Failed to ssh!") ##################################################### Part 1 ################################################################ - ##### 1. upload VPN and battery files ###### - print("Upload VPN and battery files!") - if(await upload_files(remote_host,1)!="All files uploaded successfully."): - sys.exit("Failed to upload files!") - else: - print(await upload_files(remote_host,1)) - - ##### 2. update firmware with normal image ##### gx_type = await check_GX_type(remote_host) if gx_type == "einstein\n": + ##### 2. upload VPN and battery files ###### + print("Upload VPN and battery files!") + if(await upload_files(remote_host,1)!="All files uploaded successfully."): + sys.exit("Failed to upload files!") + else: + print(await upload_files(remote_host,1)) + + ##### 3. upload VPN and battery files ###### + print("Make rc.local executable!") + print(await make_rclocal_executable(remote_host)) + + ##### 4. update firmware with normal image ##### print("Update Cerbo GX firmware now!") print(await update_cerbo_firmware(remote_host)) else: @@ -169,23 +179,14 @@ async def main(remote_host): ##################################################### Part 1 ################################################################ # Wait for remote computer to come back online + await asyncio.sleep(5) while not await check_connection(remote_host): print("Waiting for remote computer to come back online...") - await asyncio.sleep(10) # Adjust timeout as needed + await asyncio.sleep(10) # 10 seconds - ##################################################### Part 2 ################################################################ - #### 3. udpate to MK3 ##### - if (await check_mkVersion(remote_host) == "value = 1170212\n" and await check_allow_mkVersion_update_or_not(remote_host) == "0\n"): - print("Update MK3!") - print(await update_mkVersion(remote_host)) - else: - print("No need to update to MK3!") - - #### 4. import pika #### - print("Import pika!") - print(await import_pika(remote_host)) - - ##### 5. update firmware with large image ##### + #################################################### Part 2 ################################################################ + + #### 5. update firmware with large image #### print("Set update feed to official release now!") print(await set_official_update_feed(remote_host)) print("Enable large image now!") @@ -196,34 +197,54 @@ async def main(remote_host): print(await update_firmware(remote_host)) else: sys.exit("Failed to enable large image!") - ##################################################### Part 2 ################################################################ + #################################################### Part 2 ################################################################ # Wait for remote computer to come back online + await asyncio.sleep(5) while not await check_connection(remote_host): print("Waiting for remote computer to come back online...") - await asyncio.sleep(10) # Adjust timeout as needed + await asyncio.sleep(10) # 10 seconds ##################################################### Part 3 ################################################################ #### 6. resize /dev/root ##### print("Resize /dev/root now!") - print(await resize(remote_host)) + resize_result = await resize(remote_host) + if "Failed" in resize_result: + sys.exit(f"Failed to resize: {resize_result}") + else: + print(resize_result) + + #### 7. import pika #### + print("Import pika!") + import_result = await import_pika(remote_host) + if "Failed" in import_result: + sys.exit(f"Failed to import pika: {import_result}") + else: + print(import_result) - #### 7. enable Node Red ##### + #### 8. udpate to MK3 ##### + if (await check_mkVersion(remote_host) == "value = 1170212\n" and await check_allow_mkVersion_update_or_not(remote_host) == "0\n"): + print("Update MK3!") + print(await update_mkVersion(remote_host)) + else: + print("No need to update to MK3!") + + #### 9. enable Node Red ##### print("Enable Node Red now!") print(await enable_NodeRed(remote_host)) if(await check_NodeRed_enabled_or_not(remote_host) == "value = 1\n"): - ##### 8. download Node Red Dashboard ##### + ##### 10. download Node Red Dashboard ##### print("Download Node Red Dashboard now!") print(await download_node_red_dashboard(remote_host)) else: sys.exit("Failed to enable Node Red!") - ##### 9. upload files related to Node Red ##### + ##### 11. upload files related to Node Red ##### print("Upload files related to Node Red now!") if(await upload_files(remote_host,2)!="All files uploaded successfully."): sys.exit("Failed to upload files!") - #### 10. restart Node Red to load and deploy flows ##### + #### 12. restart Node Red to load and deploy flows ##### print("Disable Node Red!") if(await disable_NodeRed(remote_host) == "retval = 0\n"): print("Re-enable Node Red!") diff --git a/firmware/Cerbo_Release/update_all_cerbo_installations.sh b/firmware/Cerbo_Release/update_all_cerbo_installations.sh index 2de042038..f6b852b06 100755 --- a/firmware/Cerbo_Release/update_all_cerbo_installations.sh +++ b/firmware/Cerbo_Release/update_all_cerbo_installations.sh @@ -8,20 +8,21 @@ set -e battery_file_path="./CerboReleaseFiles/dbus-fzsonick-48tl" cerbo_release_file_path="./CerboReleaseFiles" echo -e "\n============================ Deploy ============================\n" -# Berger 10.2.2.36 and Polycom 10.2.4.96 are Cerbo with fork usb0 -# ip_addresses_usb0=("10.2.2.118" "10.2.4.155" "10.2.3.244" "10.2.4.127" "10.2.2.36" "10.2.4.96") -ip_addresses_usb0=("10.2.2.118" "10.2.4.155" "10.2.3.244" "10.2.4.127") -ip_addresses_usb1=("10.2.0.179" "10.2.1.241" ) +# Polycom 10.2.4.96 are Cerbo with fork usb0 +ip_addresses_usb0=("10.2.2.118" "10.2.4.155" "10.2.3.244" "10.2.4.127" "10.2.2.248" "10.2.2.36") +ip_addresses_usb1=("10.2.0.179" "10.2.1.241" "10.2.1.193" "10.2.2.61" "10.2.3.225") for ip_address in "${ip_addresses_usb0[@]}"; do # ssh "$username"@"$ip_address" "cd /opt/victronenergy/serial-starter && echo '$root_password' | ./stop-tty.sh ttyUSB0" - + ssh "$username"@"$ip_address" "svc -d /service/aggregator" scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/data/dbus-fzsonick-48tl/" - scp "${battery_file_path}/start.sh" "root@"$ip_address":/data/dbus-fzsonick-48tl/" - scp "${cerbo_release_file_path}/rc.local" "root@"$ip_address":/data" - scp -r "${cerbo_release_file_path}/aggregator" "root@"$ip_address":/data" + scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/opt/victronenergy/dbus-fzsonick-48tl" + ssh "$username"@"$ip_address" "svc -u /service/aggregator" + # scp "${battery_file_path}/start.sh" "root@"$ip_address":/data/dbus-fzsonick-48tl/" + # scp "${cerbo_release_file_path}/rc.local" "root@"$ip_address":/data" + # scp -r "${cerbo_release_file_path}/aggregator" "root@"$ip_address":/data" # ssh "$username"@"$ip_address" "cd /opt/victronenergy/serial-starter && echo '$root_password' | ./start-tty.sh ttyUSB0" @@ -33,7 +34,10 @@ for ip_address in "${ip_addresses_usb1[@]}"; do # ssh "$username"@"$ip_address" "cd /opt/victronenergy/serial-starter && echo '$root_password' | ./stop-tty.sh ttyUSB1" + ssh "$username"@"$ip_address" "svc -d /service/aggregator" scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/data/dbus-fzsonick-48tl/" + scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/opt/victronenergy/dbus-fzsonick-48tl" + ssh "$username"@"$ip_address" "svc -u /service/aggregator" # scp "${battery_file_path}/start.sh" "root@"$ip_address":/data/dbus-fzsonick-48tl/" # scp "${cerbo_release_file_path}/rc.local" "root@"$ip_address":/data" # scp -r "${cerbo_release_file_path}/aggregator" "root@"$ip_address":/data" diff --git a/firmware/Venus_Release/VenusReleaseFiles/PageChargingStrategy.qml b/firmware/Venus_Release/VenusReleaseFiles/PageChargingStrategy.qml index 15ad32143..76f89251d 100644 --- a/firmware/Venus_Release/VenusReleaseFiles/PageChargingStrategy.qml +++ b/firmware/Venus_Release/VenusReleaseFiles/PageChargingStrategy.qml @@ -130,6 +130,11 @@ MbPage { isCalibrationActive = true; } else if (controllerState.value === 3 && isCalibrationActive) { console.log("Stopping manual calibration charge..."); + lastEoc.setValue(previousEocValue); + console.log("Reverted lastEoc to previous value: " + previousEocValue); + isCalibrationActive = false; + } else if (controllerState.value === 3 && !isCalibrationActive) { + console.log("Stopping automatic calibration charge..."); if(previousEocValue==0){ console.log("Postpone automatic calibration charge to 1 day later."); lastEoc.setValue((new Date().getTime() - 24*60*60*1000)/1000); @@ -138,7 +143,7 @@ MbPage { console.log("Reverted lastEoc to previous value: " + previousEocValue); } isCalibrationActive = false; - } else { + } else { isCalibrationActive = false; } diff --git a/firmware/Venus_Release/VenusReleaseFiles/dbus-fzsonick-48tl/aggregator.py b/firmware/Venus_Release/VenusReleaseFiles/dbus-fzsonick-48tl/aggregator.py index be2a9013e..8b529d1b9 100755 --- a/firmware/Venus_Release/VenusReleaseFiles/dbus-fzsonick-48tl/aggregator.py +++ b/firmware/Venus_Release/VenusReleaseFiles/dbus-fzsonick-48tl/aggregator.py @@ -68,7 +68,13 @@ class AggregatedData: def push_to_s3(self, s3_config): csv_data = self.to_csv() compressed_csv = self.compress_csv_data(csv_data) - s3_path = datetime.now().strftime("%Y-%m-%d") + ".csv" + now = datetime.now() + if now.hour == 0 and now.minute < 30: + adjusted_date = now - timedelta(days=1) + else: + adjusted_date = now + + s3_path = adjusted_date.strftime("%Y-%m-%d") + ".csv" response = s3_config.create_put_request(s3_path, compressed_csv) if response.status_code != 200: print("ERROR: PUT", response.text) diff --git a/firmware/Venus_Release/Vernus Rollout Guidance.pdf b/firmware/Venus_Release/Vernus Rollout Guidance.pdf index fed5fbdd9..f1a19562d 100644 Binary files a/firmware/Venus_Release/Vernus Rollout Guidance.pdf and b/firmware/Venus_Release/Vernus Rollout Guidance.pdf differ diff --git a/firmware/Venus_Release/update_Venus.py b/firmware/Venus_Release/update_Venus.py index 51dd8f56c..cabcb7e56 100644 --- a/firmware/Venus_Release/update_Venus.py +++ b/firmware/Venus_Release/update_Venus.py @@ -29,14 +29,22 @@ async def run_rclocal(remote_host): return await run_remote_command(remote_host, command) async def stop_battery_service(remote_host): - command = "/opt/victronenergy/serial-starter/stop-tty.sh ttyUSB0" - # command = "/opt/victronenergy/serial-starter/stop-tty.sh ttyUSB1" - return await run_remote_command(remote_host, command) + command1 = "cd /opt/victronenergy/serial-starter && ./stop-tty.sh ttyUSB0" + command2 = "cd /opt/victronenergy/serial-starter && ./stop-tty.sh ttyUSB1" + + result1 = await run_remote_command(remote_host, command1) + result2 = await run_remote_command(remote_host, command2) + + return result1, result2 async def start_battery_service(remote_host): - command = "/opt/victronenergy/serial-starter/start-tty.sh ttyUSB0" - # command = "/opt/victronenergy/serial-starter/start-tty.sh ttyUSB1" - return await run_remote_command(remote_host, command) + command1 = "cd /opt/victronenergy/serial-starter && ./start-tty.sh ttyUSB0" + command2 = "cd /opt/victronenergy/serial-starter && ./start-tty.sh ttyUSB1" + + result1 = await run_remote_command(remote_host, command1) + result2 = await run_remote_command(remote_host, command2) + + return result1, result2 async def resize(remote_host): command = "sh /opt/victronenergy/swupdate-scripts/resize2fs.sh" @@ -96,30 +104,55 @@ async def import_pika(remote_host): command = f"{change_dir_command} && {install_command}" return await run_remote_command(remote_host, command) +async def make_rclocal_executable(remote_host): + command = "chmod +x /data/rc.local" + return await run_remote_command(remote_host, command) + +async def check_connection(remote_host): + result = await run_remote_command(remote_host, 'echo Connection successful') + return "Connection successful" in result + +async def restart_gui(remote_host): + command1 = "svc -d /service/gui" + command2 = "svc -u /service/gui" + result1 = await run_remote_command(remote_host, command1) + result2 = await run_remote_command(remote_host, command2) + + return result1, result2 + async def main(remote_host): - ##### 1. check whether it's Venus ###### + ##### 1. check connection ###### + print("Check connection!") + if not await check_connection(remote_host): + sys.exit("Failed to ssh!") + + ##### 2. check whether it's Venus ###### gx_type = await check_GX_type(remote_host) if gx_type == "beaglebone\n": - ##### 2. upload VPN and battery files ###### + ##### 3. upload VPN and battery files ###### print("Upload pika and battery files!") if(await upload_files(remote_host)!="All files uploaded successfully."): sys.exit("Failed to upload files!") else: print(await upload_files(remote_host)) - #### 3. import pika #### + #### 4. import pika #### print("Import pika!") print(await import_pika(remote_host)) - #### 4. resize /dev/root ##### + #### 5. resize /dev/root ##### print("Resize /dev/root now!") print(await resize(remote_host)) - # ##### 5. run rc.local ###### - # print("Run rc.local to set password, timezone and cp battery folder!") - # print(await run_rclocal(remote_host)) - ##### 5. reboot to run rc.local and update qml ###### - print("Reboot!") + #### 6. stop battery service ###### + print("Stop battery service!") + print(await stop_battery_service(remote_host)) + ##### 7. run rc.local ###### + print("Run rc.local!") print(await run_rclocal(remote_host)) - - + ##### 8. start battery service ###### + print("Start battery service!") + print(await start_battery_service(remote_host)) + ##### 9. restart gui ###### + print("Restart gui!") + print(await restart_gui(remote_host)) else: sys.exit("It's not Venus GX!") diff --git a/firmware/Venus_Release/update_all_venus_installations.sh b/firmware/Venus_Release/update_all_venus_installations.sh index cf86c1a13..6bd7f5907 100755 --- a/firmware/Venus_Release/update_all_venus_installations.sh +++ b/firmware/Venus_Release/update_all_venus_installations.sh @@ -8,24 +8,26 @@ set -e battery_file_path="./VenusReleaseFiles/dbus-fzsonick-48tl" venus_release_file_path="./VenusReleaseFiles" echo -e "\n============================ Deploy ============================\n" -# Berger 10.2.2.36 and Polycom 10.2.4.96 are Cerbo with fork usb0 +# Polycom 10.2.4.96 are Cerbo with fork usb0 # Grundmann 10.2.0.155 failed with ssh" # Wiest 10.2.0.209 failed with ssh" # Buecheler 10.2.0.224 failed with ssh" -# ip_addresses_usb0=("10.2.1.97" "10.2.0.104" "10.2.1.159" "10.2.0.227" "10.2.2.36" "10.2.4.96" "10.2.0.224" "10.2.0.155" "10.2.0.209") -ip_addresses_usb0=("10.2.1.97" "10.2.0.104" "10.2.1.159" "10.2.0.227" "10.2.2.36" "10.2.4.96") -ip_addresses_usb1=("10.2.1.35") +ip_addresses_usb0=("10.2.1.97" "10.2.0.104" "10.2.1.159" "10.2.0.227" "10.2.4.96") +ip_addresses_usb1=("10.2.1.35" "10.2.0.211") for ip_address in "${ip_addresses_usb0[@]}"; do # ssh "$username"@"$ip_address" "cd /opt/victronenergy/serial-starter && echo '$root_password' | ./stop-tty.sh ttyUSB0" + ssh "$username"@"$ip_address" "svc -d /service/aggregator" scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/data/dbus-fzsonick-48tl/" - scp "${battery_file_path}/start.sh" "root@"$ip_address":/data/dbus-fzsonick-48tl/" - scp "${battery_file_path}/service/run" "root@"$ip_address":/data/dbus-fzsonick-48tl/service" - scp "${venus_release_file_path}/rc.local" "root@"$ip_address":/data" - scp -r "${venus_release_file_path}/aggregator" "root@"$ip_address":/data" + scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/opt/victronenergy/dbus-fzsonick-48tl" + ssh "$username"@"$ip_address" "svc -u /service/aggregator" + # scp "${battery_file_path}/start.sh" "root@"$ip_address":/data/dbus-fzsonick-48tl/" + # scp "${battery_file_path}/service/run" "root@"$ip_address":/data/dbus-fzsonick-48tl/service" + # scp "${venus_release_file_path}/rc.local" "root@"$ip_address":/data" + # scp -r "${venus_release_file_path}/aggregator" "root@"$ip_address":/data" # ssh "$username"@"$ip_address" "cd /opt/victronenergy/serial-starter && echo '$root_password' | ./start-tty.sh ttyUSB0" @@ -38,11 +40,14 @@ for ip_address in "${ip_addresses_usb1[@]}"; do # ssh "$username"@"$ip_address" "cd /opt/victronenergy/serial-starter && echo '$root_password' | ./stop-tty.sh ttyUSB1" + ssh "$username"@"$ip_address" "svc -d /service/aggregator" scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/data/dbus-fzsonick-48tl/" - scp "${battery_file_path}/start.sh" "root@"$ip_address":/data/dbus-fzsonick-48tl/" - scp "${battery_file_path}/service/run" "root@"$ip_address":/data/dbus-fzsonick-48tl/service" - scp "${venus_release_file_path}/rc.local" "root@"$ip_address":/data" - scp -r "${venus_release_file_path}/aggregator" "root@"$ip_address":/data" + scp "${battery_file_path}/aggregator.py" "root@"$ip_address":/opt/victronenergy/dbus-fzsonick-48tl" + ssh "$username"@"$ip_address" "svc -u /service/aggregator" + # scp "${battery_file_path}/start.sh" "root@"$ip_address":/data/dbus-fzsonick-48tl/" + # scp "${battery_file_path}/service/run" "root@"$ip_address":/data/dbus-fzsonick-48tl/service" + # scp "${venus_release_file_path}/rc.local" "root@"$ip_address":/data" + # scp -r "${venus_release_file_path}/aggregator" "root@"$ip_address":/data" # ssh "$username"@"$ip_address" "cd /opt/victronenergy/serial-starter && echo '$root_password' | ./start-tty.sh ttyUSB1"