Skip to content

Fix/manual null scenario#1403

Open
AECohn wants to merge 2 commits intomainfrom
fix/manualNullScenario
Open

Fix/manual null scenario#1403
AECohn wants to merge 2 commits intomainfrom
fix/manualNullScenario

Conversation

@AECohn
Copy link
Contributor

@AECohn AECohn commented Mar 20, 2026

This pull request introduces a small but important change to the SetRoomCombinationScenario method in the EssentialsRoomCombiner class. The update ensures that the scenario is activated immediately, preventing _currentScenario from being null when starting in manual mode.

  • Ensured that ChangeScenario(scenario) is called to activate the scenario and avoid a null _currentScenario when starting in manual mode.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ensures the room combiner’s current scenario is set when manually applying a combination scenario, preventing CurrentScenario/_currentScenario from remaining null in manual mode flows.

Changes:

  • After manually applying partition states for a scenario, calls ChangeScenario(scenario) to set/activate the scenario.
  • Minor formatting-only change within the partition loop block.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
}
// Activates the scenario to prevent _currentScenario from being null when starting in manual mode.
ChangeScenario(scenario);
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ChangeScenario returns Task (async) and is being invoked without awaiting or otherwise observing the task. This can hide exceptions from Activate/Deactivate and can also allow overlapping scenario changes if this method is called multiple times quickly. Consider explicitly firing-and-forgetting with exception logging (e.g., capturing the returned task and handling faults) or introducing a serialized/queued scenario-change mechanism so only one activation runs at a time.

Suggested change
ChangeScenario(scenario);
var _ = ChangeScenario(scenario).ContinueWith(t =>
{
var ex = t.Exception != null ? t.Exception.Flatten() : null;
if (ex != null)
{
Debug.LogMessage(LogEventLevel.Error, this,
"Error changing scenario to '{0}': {1}", scenario.Key, ex);
}
}, TaskContinuationOptions.OnlyOnFaulted);

Copilot uses AI. Check for mistakes.
{
Debug.LogMessage(LogEventLevel.Debug, this, "Unable to find partition with key: '{0}'", partitionState.PartitionKey);
}
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There appears to be trailing whitespace after the closing brace on this line. Please remove the extra spaces to avoid noisy diffs and keep formatting consistent.

Suggested change
}
}

Copilot uses AI. Check for mistakes.
@andrew-welker
Copy link
Contributor

@AECohn Can you post a config snippet for the room combiner from the config that was running when you saw this issue? The way this should work is that the default scenario has a set of partitions configured that then have their state set based on the selected scenario, then the partition feedback(s) update with their manually-set state, and that then triggers the DetermineRoomCombinationScenario which calls the ChangeScenario function.

My concern is that calling ChangeScenario as you've added could cause a runway loop.

It's possible that something is checking for the current scenario too early in the start up secquence, as the initial scenario, whether manual or automatic, isn't set until all devices have completed initialization, which doesn't happen until AFTER all of the activation steps.

It's also possible that the configuration isn't setup correctly for the partitions.

@AECohn
Copy link
Contributor Author

AECohn commented Mar 20, 2026

@AECohn Can you post a config snippet for the room combiner from the config that was running when you saw this issue? The way this should work is that the default scenario has a set of partitions configured that then have their state set based on the selected scenario, then the partition feedback(s) update with their manually-set state, and that then triggers the DetermineRoomCombinationScenario which calls the ChangeScenario function.

My concern is that calling ChangeScenario as you've added could cause a runway loop.

It's possible that something is checking for the current scenario too early in the start up secquence, as the initial scenario, whether manual or automatic, isn't set until all devices have completed initialization, which doesn't happen until AFTER all of the activation steps.

It's also possible that the configuration isn't setup correctly for the partitions.
@andrew-welker
This is the config snippet that wasn't working:

{ "key": "essentialsroomcombiner", "name": "Room Combiner", "type": "essentialsroomcombiner", "group": "generic", "properties": { defaultToManualMode": true, "defaultScenarioKey": "divided", "scenarioChangeDebounceTimeSeconds": 10, disableAutoMode": true, "roomKeys": [ "roomB", "roomA", "roomC" ],

setting defaultToManulMode false and removing disableAutoMode fixed it, but I had to update Essentials to get this config to render

@andrew-welker
Copy link
Contributor

Is that the whole config for the combiner? It doesn't seem to be a complete object.

@AECohn
Copy link
Contributor Author

AECohn commented Mar 21, 2026

Is that the whole config for the combiner? It doesn't seem to be a complete object.

Here's the full object:

{
       "key": "essentialsroomcombiner",
       "name": "Room Combiner",
       "type": "essentialsroomcombiner",
       "group": "generic",
       "properties": {
         "defaultToManualMode": true,
         "defaultScenarioKey": "divided",
         "scenarioChangeDebounceTimeSeconds": 10,
         "disableAutoMode": true,
         "roomKeys": [
           "roomB",
           "roomA",
           "roomC"
         ],
         "partitions": [
           {
             "key": "roomABPartition",
             "name": "Room A/B",
             "adjacentRoomKeys": [
               "roomA",
               "roomB"
             ]
           },
           {
             "key": "roomACPartition",
             "name": "Room A/C",
             "adjacentRoomKeys": [
               "roomA",
               "roomC"
             ]
           }
         ],
         "scenarios": [
           {
             "key": "abCombined",
             "name": "Rooms 7002 and 7003 are Combined",
             "partitionStates": [
               {
                 "partitionKey": "roomABPartition",
                 "partitionSensedState": false
               },
               {
                 "partitionKey": "roomACPartition",
                 "partitionSensedState": true
               }
             ],
             "uiMap": {
               "primary": "roomA",
               "roomA": "roomAB",
               "roomB": "lockout",
               "roomC": "roomC"
             },
             "activationActions": [
               {
                 "deviceKey": "roomAB",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "roomC",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "dsp",
                 "methodName": "RecallPreset",
                 "params": [
                   "AB_COMBINED"
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/35",
                   1010
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/38",
                   1030
                 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 2 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Presenter Cam 7003" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 4, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 4, 3 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 4, "Presenter Cam 7002" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 5, "other" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 5, 4 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 5, "Unused in AB" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "other" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 7 ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Unused when combined" ]
               }
             ],
             "deactivationActions": [
               {
                 "deviceKey": "roomAB",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "roomC",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "navigatorB",
                 "methodName": "CloseWebViewController"
               },
               {
                 "deviceKey": "navigatorC",
                 "methodName": "CloseWebViewController"
               }
             ]
           },
           {
             "key": "acCombined",
             "name": "Rooms 7003 and 7004 are Combined",
             "partitionStates": [
               {
                 "partitionKey": "roomABPartition",
                 "partitionSensedState": true
               },
               {
                 "partitionKey": "roomACPartition",
                 "partitionSensedState": false
               }
             ],
             "uiMap": {
               "primary": "roomA",
               "roomA": "roomAC",
               "roomB": "roomB",
               "roomC": "lockout"
             },
             "activationActions": [
               {
                 "deviceKey": "roomA",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "roomAC",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "dsp",
                 "methodName": "RecallPreset",
                 "params": [
                   "AC_COMBINED"
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/35",
                   1020
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/38",
                   1010
                 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 2 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Presenter Cam 7003" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 4, "other" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 4, 3 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 4, "Unused in AC" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 5, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 5, 4 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 5, "Presenter Cam 7004" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "other" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 7 ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Unused when combined" ]
               }
             ],
             "deactivationActions": [
               {
                 "deviceKey": "roomA",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "roomAC",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "navigatorB",
                 "methodName": "CloseWebViewController"
               },
               {
                 "deviceKey": "navigatorC",
                 "methodName": "CloseWebViewController"
               }
             ]
           },
           {
             "key": "abcCombined",
             "name": "All Rooms Combined",
             "partitionStates": [
               {
                 "partitionKey": "roomABPartition",
                 "partitionSensedState": false
               },
               {
                 "partitionKey": "roomACPartition",
                 "partitionSensedState": false
               }
             ],
             "uiMap": {
               "primary": "roomA",
               "roomA": "roomABC",
               "roomB": "lockout",
               "roomC": "lockout"
             },
             "activationActions": [
               {
                 "deviceKey": "roomABC",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "dsp",
                 "methodName": "RecallPreset",
                 "params": [
                   "ABC_COMBINED"
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/35",
                   1010
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/38",
                   1010
                 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 2 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Presenter Cam 7003" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 4, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 4, 3 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 4, "Presenter Cam 7002" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 5, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 5, 4 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 5, "Presenter Cam 7004" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "other" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 7 ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Unused when combined" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "other" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 7 ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Unused when combined" ]
               }
             ],
             "deactivationActions": [
               {
                 "deviceKey": "roomABC",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "navigatorB",
                 "methodName": "CloseWebViewController"
               },
               {
                 "deviceKey": "navigatorC",
                 "methodName": "CloseWebViewController"
               }
             ]
           },
           {
             "key": "divided",
             "name": "Rooms are Divided",
             "partitionStates": [
               {
                 "partitionKey": "roomABPartition",
                 "partitionSensedState": true
               },
               {
                 "partitionKey": "roomACPartition",
                 "partitionSensedState": true
               }
             ],
             "uiMap": {
               "primary": null,
               "roomA": "roomA",
               "roomB": "roomB",
               "roomC": "roomC"
             },
             "activationActions": [
               {
                 "deviceKey": "roomA",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "roomB",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "roomC",
                 "methodName": "CustomActivate"
               },
               {
                 "deviceKey": "dsp",
                 "methodName": "RecallPreset",
                 "params": [
                   "ALL_DIVIDED"
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/35",
                   1020
                 ]
               },
               {
                 "deviceKey": "netgearSwitch-1",
                 "methodName": "ChangeVlan",
                 "params": [
                   "0/38",
                   1030
                 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "camera" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 2 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Presenter Cam" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 4, "other" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 4, 3 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 4, "Unused Divided" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputSourceType",
                 "params": [ 5, "other" ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetInputCameraId",
                 "params": [ 5, 4 ]
               },
               {
                 "deviceKey": "codecA",
                 "methodName": "SetCameraName",
                 "params": [ 5, "Unused Divided" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "camera" ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 7 ]
               },
               {
                 "deviceKey": "codecB",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Presenter Cam" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputSourceType",
                 "params": [ 1, "camera" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputCameraId",
                 "params": [ 1, 1 ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetCameraName",
                 "params": [ 1, "Audience Cam" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputSourceType",
                 "params": [ 2, "camera" ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetInputCameraId",
                 "params": [ 2, 7 ]
               },
               {
                 "deviceKey": "codecC",
                 "methodName": "SetCameraName",
                 "params": [ 2, "Presenter Cam" ]
               }
             ],
             "deactivationActions": [
               {
                 "deviceKey": "roomA",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "roomB",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "roomC",
                 "methodName": "Deactivate"
               },
               {
                 "deviceKey": "navigatorB",
                 "methodName": "CloseWebViewController"
               },
               {
                 "deviceKey": "navigatorC",
                 "methodName": "CloseWebViewController"
               }
             ]
           }
         ]
       }
     }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants