allenporter / pyrainbird

Rain Bird Controller in Python

Home Page:https://allenporter.github.io/pyrainbird/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ESP-ME program schedule is incorrect

tsfran opened this issue · comments

commented

Thanks for all your work on this! I've been experimenting with version 2.0.0 on my ESP-ME and it seems to be working great.

One thing I noticed is using get_schedule_command s seems to give wonky responses for the durations. That is, I have 4 programs (0-3) but only 3 durations. I thought there would be at least four durations: one for each program. Furthermore, the durations do not appear to be in any order corresponding to the program. For example, my program 0, zone 0 and zone 1 should show durations of 30 and 27 minutes, respectively. However, it seems they return 23 and 0 minutes, respectively.

I am inexperienced with python and may very well have missed something obvious to everyone else.

Thanks!

{'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}

@tsfran thank you, very helpful. I only ever test on a single device, and every device has a bit of a different flavor of request and response codes. .I'm happy to fix this if you can help by getting some samples of the raw input/outputs for the requests/

What would be really helpful is if we could turn up debug logging for the async_client package, then we can see all the relevant input and outputs, and I should be able to write some unit tests to reproduce the problem -- similar to something like this: https://github.com/allenporter/pyrainbird/blob/main/tests/testdata/schedule.yaml

If you are using the example CLI in the examples directory this can be done with --log-level or if using in some other library you can borrow its code to turn up logging.

commented

Using python version 3.9.13 and command line py examples\rainbird_tool.py --log-level=debug get_schedule I get this:

DEBUG:pyrainbird.async_client:Request (ModelAndVersionRequest): 02
DEBUG:pyrainbird.async_client:Request: {"id": 1680547826.7245936, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "02", "length": 1}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":5, "data":"8200070209"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: 8200070209
DEBUG:pyrainbird.async_client:Response: {'type': 'ModelAndVersionResponse', 'modelID': 7, 'protocolRevisionMajor': 2, 'protocolRevisionMinor': 9}
DEBUG:pyrainbird.async_client:Request (AvailableStationsRequest): 0300
DEBUG:pyrainbird.async_client:Request: {"id": 1680547827.2296617, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "0300", "length": 2}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":6, "data":"83007F000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: 83007F000000
DEBUG:pyrainbird.async_client:Response: {'type': 'AvailableStationsResponse', 'pageNumber': 0, 'setStations': 2130706432}
DEBUG:pyrainbird.async_client:Loading schedule for 22 zones
DEBUG:pyrainbird.async_client:Sending schedule commands: ['00', '0010', '0011', '0012', '0013', '0060', '0061', '0062', '0063', '0080', '0081', '0082', '0083', '0084', '0085', '0086', '0087', '0088', '0089', '008a']
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200000
DEBUG:pyrainbird.async_client:Request: {"id": 1680547828.0381815, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200000", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":7, "data":"A0000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200010
DEBUG:pyrainbird.async_client:Request: {"id": 1680547828.5542226, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200010", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A00010290403004B01"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00010290403004B01
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200011
DEBUG:pyrainbird.async_client:Request: {"id": 1680547829.0832677, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200011", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A000117F0301006402"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A000117F0301006402
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200012
DEBUG:pyrainbird.async_client:Request: {"id": 1680547829.6052852, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200012", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A00012550200006401"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00012550200006401
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200013
DEBUG:pyrainbird.async_client:Request: {"id": 1680547830.1567688, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200013", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A000137D0200006401"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A000137D0200006401
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200060
DEBUG:pyrainbird.async_client:Request: {"id": 1680547830.7297115, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200060", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A0006001B3FFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0006001B3FFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200061
DEBUG:pyrainbird.async_client:Request: {"id": 1680547831.2816975, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200061", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A00061FFFFFFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00061FFFFFFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200062
DEBUG:pyrainbird.async_client:Request: {"id": 1680547831.8212013, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200062", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A00062FFFFFFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00062FFFFFFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200063
DEBUG:pyrainbird.async_client:Request: {"id": 1680547832.384662, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200063", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A00063FFFFFFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00063FFFFFFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200080
DEBUG:pyrainbird.async_client:Request: {"id": 1680547832.9261656, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200080", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A000800017001E000F00000015001B000D0000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A000800017001E000F00000015001B000D0000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200081
DEBUG:pyrainbird.async_client:Request: {"id": 1680547833.5105875, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200081", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A00081001B00230011000000170019000E0000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00081001B00230011000000170019000E0000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200082
DEBUG:pyrainbird.async_client:Request: {"id": 1680547834.084548, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200082", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008200220000001600140000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008200220000001600140000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200083
DEBUG:pyrainbird.async_client:Request: {"id": 1680547834.6624658, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200083", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008300000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008300000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 6, 'durations': [0, 0, 0]}, {'zone': 7, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200084
DEBUG:pyrainbird.async_client:Request: {"id": 1680547835.2259276, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200084", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008400000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008400000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 8, 'durations': [0, 0, 0]}, {'zone': 9, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200085
DEBUG:pyrainbird.async_client:Request: {"id": 1680547835.785441, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200085", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008500000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008500000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 10, 'durations': [0, 0, 0]}, {'zone': 11, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200086
DEBUG:pyrainbird.async_client:Request: {"id": 1680547836.3583856, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200086", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008600000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008600000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 12, 'durations': [0, 0, 0]}, {'zone': 13, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200087
DEBUG:pyrainbird.async_client:Request: {"id": 1680547836.9248416, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200087", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008700000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008700000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 14, 'durations': [0, 0, 0]}, {'zone': 15, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200088
DEBUG:pyrainbird.async_client:Request: {"id": 1680547837.486805, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200088", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008800000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008800000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 16, 'durations': [0, 0, 0]}, {'zone': 17, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200089
DEBUG:pyrainbird.async_client:Request: {"id": 1680547838.2923217, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200089", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008900000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008900000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 18, 'durations': [0, 0, 0]}, {'zone': 19, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 20008A
DEBUG:pyrainbird.async_client:Request: {"id": 1680547838.8567803, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "20008A", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008A00000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008A00000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 20, 'durations': [0, 0, 0]}, {'zone': 21, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.data:Mismatched number of program durations: 3 != 4: {'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1, 'starts': [435, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.data:Mismatched number of program durations: 3 != 4: {'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1, 'starts': [435, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.data:Mismatched number of program durations: 3 != 4: {'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1, 'starts': [435, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.data:Mismatched number of program durations: 3 != 4: {'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1, 'starts': [435, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.data:Mismatched number of program durations: 3 != 4: {'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1, 'starts': [435, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.data:Mismatched number of program durations: 3 != 4: {'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1, 'starts': [435, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}
DEBUG:pyrainbird.data:Mismatched number of program durations: 3 != 4: {'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'programInfo': [{'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 3, 'permanentDaysOff': 0, 'reserved': 75, 'frequency': 1, 'starts': [435, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}, {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 0, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1, 'starts': [65535, 65535, 65535, 65535, 65535, 65535], 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}, 'durations': []}], 'programStartInfo': [{'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}, {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}, {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}], 'durations': [{'zone': 0, 'durations': [23, 30, 15]}, {'zone': 1, 'durations': [0, 21, 27]}, {'zone': 2, 'durations': [27, 35, 17]}, {'zone': 3, 'durations': [0, 23, 25]}, {'zone': 4, 'durations': [34, 0, 22]}, {'zone': 5, 'durations': [20, 0, 0]}, {'zone': 6, 'durations': [0, 0, 0]}]}
controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False) programs=[Program(program=0, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=4, synchro=3, starts=[datetime.time(7, 15)], durations=[], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=1, frequency=<ProgramFrequency.ODD: 2>, days_of_week=set(), period=None, synchro=1, starts=[], durations=[], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=2, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=2, synchro=0, starts=[], durations=[], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=3, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=2, synchro=0, starts=[], durations=[], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False))]

Thanks, that's super helpful. We can even see the warning showing the issue in your example where its detecting something is off. I think I found the culprit in https://github.com/allenporter/pyrainbird/pull/151/files where there was a hard coded assumption of only 3 programs.

Now in the test examples, it returns the correct length of the response. I noticed in these examples all the durations for the 4th program are all zero. Is that correct in your case? If you confirm that is right I can proceed.

commented

That does the trick!

The fourth program has zero durations for all but zone 4 (indexed from 0) that is 20.

You probably know this already but it looks like the durations are the seasonally adjusted (aka water budgeted, aka "reserved') run times for each zone.

One more thing and, again, you probably are well aware of this but the output from examples\rainbird_tool.py get_schedule now has output like:
durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=1800))
that I'm guessing is not what is intended.

Example new output from rainbird_tool get_schedule:

controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False) programs=[Program(program=0, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=4, synchro=2, starts=[datetime.time(7, 15)], durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=1800)), ZoneDuration(zone=2, duration=datetime.timedelta(seconds=1620)), ZoneDuration(zone=3, duration=datetime.timedelta(seconds=2100)), ZoneDuration(zone=4, duration=datetime.timedelta(seconds=1800)), ZoneDuration(zone=5, duration=datetime.timedelta(seconds=2700))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=1, frequency=<ProgramFrequency.ODD: 2>, days_of_week=set(), period=None, synchro=1, starts=[], durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=1800)), ZoneDuration(zone=2, duration=datetime.timedelta(seconds=1620)), ZoneDuration(zone=3, duration=datetime.timedelta(seconds=2100)), ZoneDuration(zone=4, duration=datetime.timedelta(seconds=1500))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=2, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=2, synchro=1, starts=[], durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=900)), ZoneDuration(zone=2, duration=datetime.timedelta(seconds=780)), ZoneDuration(zone=3, duration=datetime.timedelta(seconds=1020)), ZoneDuration(zone=4, duration=datetime.timedelta(seconds=840)), ZoneDuration(zone=5, duration=datetime.timedelta(seconds=1320))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=3, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=2, synchro=1, starts=[], durations=[ZoneDuration(zone=5, duration=datetime.timedelta(seconds=1200))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False))]
commented

One more thing I just noticed with new data reads from this morning (it's raining and the rain sensor is wet and indicating 'true' by other methods): the 'rainSensor' is still showing '0' with the rainbird_tool get_schedule. Maybe 'rainSensor' means something else?

Full debug output:

DEBUG:pyrainbird.async_client:Request (ModelAndVersionRequest): 02
DEBUG:pyrainbird.async_client:Request: {"id": 1680602742.8194437, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "02", "length": 1}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":5, "data":"8200070209"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: 8200070209
DEBUG:pyrainbird.async_client:Response: {'type': 'ModelAndVersionResponse', 'modelID': 7, 'protocolRevisionMajor': 2, 'protocolRevisionMinor': 9}
DEBUG:pyrainbird.async_client:Request (AvailableStationsRequest): 0300
DEBUG:pyrainbird.async_client:Request: {"id": 1680602743.325109, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "0300", "length": 2}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":6, "data":"83007F000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: 83007F000000
DEBUG:pyrainbird.async_client:Response: {'type': 'AvailableStationsResponse', 'pageNumber': 0, 'setStations': 2130706432}
DEBUG:pyrainbird.async_client:Loading schedule for 22 zones
DEBUG:pyrainbird.async_client:Sending schedule commands: ['00', '0010', '0011', '0012', '0013', '0060', '0061', '0062', '0063', '0080', '0081', '0082', '0083', '0084', '0085', '0086', '0087', '0088', '0089', '008a']
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200000
DEBUG:pyrainbird.async_client:Request: {"id": 1680602743.8331325, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200000", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":7, "data":"A0000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'controllerInfo': {'stationDelay': 0, 'rainDelay': 0, 'rainSensor': 0}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200010
DEBUG:pyrainbird.async_client:Request: {"id": 1680602744.370636, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200010", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A00010290402006401"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00010290402006401
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 0, 'daysOfWeekMask': 41, 'period': 4, 'synchro': 2, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200011
DEBUG:pyrainbird.async_client:Request: {"id": 1680602744.8937914, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200011", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A000117F0301006402"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A000117F0301006402
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 1, 'daysOfWeekMask': 127, 'period': 3, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 2}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200012
DEBUG:pyrainbird.async_client:Request: {"id": 1680602745.4260674, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200012", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A00012550201006401"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00012550201006401
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 2, 'daysOfWeekMask': 85, 'period': 2, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200013
DEBUG:pyrainbird.async_client:Request: {"id": 1680602745.9591076, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200013", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":9, "data":"A000137D0201006401"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A000137D0201006401
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programInfo': {'program': 3, 'daysOfWeekMask': 125, 'period': 2, 'synchro': 1, 'permanentDaysOff': 0, 'reserved': 100, 'frequency': 1}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200060
DEBUG:pyrainbird.async_client:Request: {"id": 1680602746.478823, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200060", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A0006001B3FFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0006001B3FFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 0, 'startTime': [435, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200061
DEBUG:pyrainbird.async_client:Request: {"id": 1680602747.023317, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200061", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A00061FFFFFFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00061FFFFFFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 1, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200062
DEBUG:pyrainbird.async_client:Request: {"id": 1680602747.562393, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200062", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A00062FFFFFFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00062FFFFFFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 2, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200063
DEBUG:pyrainbird.async_client:Request: {"id": 1680602748.5591028, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200063", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":15, "data":"A00063FFFFFFFFFFFFFFFFFFFFFFFF"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00063FFFFFFFFFFFFFFFFFFFFFFFF
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'programStartInfo': {'program': 3, 'startTime': [65535, 65535, 65535, 65535, 65535, 65535]}}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200080
DEBUG:pyrainbird.async_client:Request: {"id": 1680602749.1125376, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200080", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A00080001E001E000F0000001B001B000D0000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00080001E001E000F0000001B001B000D0000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 0, 'durations': [30, 30, 15, 0]}, {'zone': 1, 'durations': [27, 27, 13, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200081
DEBUG:pyrainbird.async_client:Request: {"id": 1680602749.6953938, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200081", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A000810023002300110000001E0019000E0000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A000810023002300110000001E0019000E0000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 2, 'durations': [35, 35, 17, 0]}, {'zone': 3, 'durations': [30, 25, 14, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200082
DEBUG:pyrainbird.async_client:Request: {"id": 1680602750.2723484, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200082", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A00082002D0000001600140000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A00082002D0000001600140000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 4, 'durations': [45, 0, 22, 20]}, {'zone': 5, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200083
DEBUG:pyrainbird.async_client:Request: {"id": 1680602750.8613744, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200083", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008300000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008300000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 6, 'durations': [0, 0, 0, 0]}, {'zone': 7, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200084
DEBUG:pyrainbird.async_client:Request: {"id": 1680602751.43357, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200084", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008400000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008400000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 8, 'durations': [0, 0, 0, 0]}, {'zone': 9, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200085
DEBUG:pyrainbird.async_client:Request: {"id": 1680602751.99355, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200085", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008500000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008500000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 10, 'durations': [0, 0, 0, 0]}, {'zone': 11, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200086
DEBUG:pyrainbird.async_client:Request: {"id": 1680602752.557554, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200086", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008600000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008600000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 12, 'durations': [0, 0, 0, 0]}, {'zone': 13, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200087
DEBUG:pyrainbird.async_client:Request: {"id": 1680602753.1309955, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200087", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008700000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008700000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 14, 'durations': [0, 0, 0, 0]}, {'zone': 15, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200088
DEBUG:pyrainbird.async_client:Request: {"id": 1680602753.705217, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200088", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008800000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008800000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 16, 'durations': [0, 0, 0, 0]}, {'zone': 17, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 200089
DEBUG:pyrainbird.async_client:Request: {"id": 1680602754.2869487, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "200089", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008900000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008900000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 18, 'durations': [0, 0, 0, 0]}, {'zone': 19, 'durations': [0, 0, 0, 0]}]}
DEBUG:pyrainbird.async_client:Request (RetrieveScheduleRequest): 20008A
DEBUG:pyrainbird.async_client:Request: {"id": 1680602754.85907, "jsonrpc": "2.0", "method": "tunnelSip", "params": {"data": "20008A", "length": 3}}
DEBUG:pyrainbird.async_client:Response: {"jsonrpc": "2.0", "result":{"length":19, "data":"A0008A00000000000000000000000000000000"}, "id": 0}
DEBUG:pyrainbird.async_client:Response from line: A0008A00000000000000000000000000000000
DEBUG:pyrainbird.async_client:Response: {'type': 'RetrieveScheduleResponse', 'durations': [{'zone': 20, 'durations': [0, 0, 0, 0]}, {'zone': 21, 'durations': [0, 0, 0, 0]}]}
controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False) programs=[Program(program=0, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=4, synchro=2, starts=[datetime.time(7, 15)], durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=1800)), ZoneDuration(zone=2, duration=datetime.timedelta(seconds=1620)), ZoneDuration(zone=3, duration=datetime.timedelta(seconds=2100)), ZoneDuration(zone=4, duration=datetime.timedelta(seconds=1800)), ZoneDuration(zone=5, duration=datetime.timedelta(seconds=2700))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=1, frequency=<ProgramFrequency.ODD: 2>, days_of_week=set(), period=None, synchro=1, starts=[], durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=1800)), ZoneDuration(zone=2, duration=datetime.timedelta(seconds=1620)), ZoneDuration(zone=3, duration=datetime.timedelta(seconds=2100)), ZoneDuration(zone=4, duration=datetime.timedelta(seconds=1500))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=2, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=2, synchro=1, starts=[], durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=900)), ZoneDuration(zone=2, duration=datetime.timedelta(seconds=780)), ZoneDuration(zone=3, duration=datetime.timedelta(seconds=1020)), ZoneDuration(zone=4, duration=datetime.timedelta(seconds=840)), ZoneDuration(zone=5, duration=datetime.timedelta(seconds=1320))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False)), Program(program=3, frequency=<ProgramFrequency.CYCLIC: 1>, days_of_week=set(), period=2, synchro=1, starts=[], durations=[ZoneDuration(zone=5, duration=datetime.timedelta(seconds=1200))], controller_info=ControllerInfo(station_delay=0, rain_delay=0, rain_sensor=False))]

That does the trick!

The fourth program has zero durations for all but zone 4 (indexed from 0) that is 20.

You probably know this already but it looks like the durations are the seasonally adjusted (aka water budgeted, aka "reserved') run times for each zone.

Can you elaborate on if this is working as intended or not?

One more thing and, again, you probably are well aware of this but the output from examples\rainbird_tool.py get_schedule now has output like: durations=[ZoneDuration(zone=1, duration=datetime.timedelta(seconds=1800)) that I'm guessing is not what is intended.

I'm having a little trouble following what the problem is. Can you help me understand what you are seeing vs what you are expecting? I'm not understanding what the problem is here.

One more thing I just noticed with new data reads from this morning (it's raining and the rain sensor is wet and indicating 'true' by other methods): the 'rainSensor' is still showing '0' with the rainbird_tool get_schedule. Maybe 'rainSensor' means something else?

OK thanks for that detail. It is helpful to know that it is not in sync with the other rain sensor return values. I can do some investigation on this.

commented

Can you elaborate on if this is working as intended or not?

This is perfectly fine for me.

I'm having a little trouble following what the problem is. Can you help me understand what you are seeing vs what you are expecting? I'm not understanding what the problem is here.

Not a problem per se but it seems different from most other styles of output that are just a number.

OK thanks for that detail. It is helpful to know that it is not in sync with the other rain sensor return values. I can do some investigation on this.

Thanks for all your help!

OK sounds like we're good here then. I've tagged a new library release and will mark as fixed. Please feel free to report any other issues with ESP-ME and i'd be happy to address them.