Repository: pwr-Solaar/Solaar

Issue:
bad key in divert-keys value in config file causes AttributeError
I have user-defined rules within Solaar Rule Editor for MX Master 2S mouse. Lately my bindings stopped to work (nothing happens after pressing key on mouse).

Defined rules:
Rule 1
- Key: `Mouse Gesture Button (00C3) (pressed)`
- Key press: `KP_Enter`

Rule 2
- Key: `Smart Shift (00C4) (pressed)`
- Key press: `Control_L + v`

Unifying receiver version: `RQR12.10_B0032`, bootloader: `BOT01.02_B0015`
Python version: `3.10.7`
Solaar version: `1.1.5`


Debug mode throws only below lines after pressing any of buttons assigned to Rule

```bash
ERROR [ReceiverListener:hidraw0] logitech_receiver.settings: invalid choice 0 for 215
WARNING [ReceiverListener:hidraw0] logitech_receiver.settings: divert-keys: error applying value {82: 0, 83: 0, 86: 0, 195: 1, 196: 1, 215: 0, '0': 2} so ignore it (<Device(2,4069,Wireless Mouse MX Master 2S,DB37EDED)>)
ERROR [ReceiverListener:hidraw0] logitech_receiver.listener: processing Notification(11,2,0A,00,00000000000000000000000000000000)
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/logitech_receiver/listener.py", line 188, in run
    self._notifications_callback(n)
  File "/usr/lib/python3.10/site-packages/solaar/listener.py", line 264, in _notifications_handler
    _notifications.process(dev, n)
  File "/usr/lib/python3.10/site-packages/logitech_receiver/notifications.py", line 60, in process
    return _process_device_notification(device, status, notification)
  File "/usr/lib/python3.10/site-packages/logitech_receiver/notifications.py", line 169, in _process_device_notification
    handling_ret = device.handle_notification(n)
  File "/usr/lib/python3.10/site-packages/logitech_receiver/device.py", line 417, in handle_notification
    ret = h(self, n)
  File "/usr/lib/python3.10/site-packages/logitech_receiver/settings.py", line 1431, in handler
    if int(k.key) in cids:  # initiating key that was pressed
AttributeError: 'NoneType' object has no attribute 'key'
```

Sometimes when I plug out and plug in unifying receiver while Solaar is running everything start to work normally. 

How can I help to nail down the issue?

<details>
  <summary>Config file content</summary>

Config

```yaml
- 1.1.5
- _NAME: Wireless Keyboard K270 (unifying)
  _absent: [hi-res-scroll, lowres-smooth-scroll, hires-smooth-invert, hires-smooth-resolution, smart-shift, thumb-scroll-mode, thumb-scroll-invert, onboard_profiles,
    report_rate, pointer_speed, dpi, dpi-sliding, speed-change, mouse-gestures, backlight, backlight-timed, fn-swap, reprogrammable-keys, persistent-remappable-keys,
    divert-keys, disable-keyboard-keys, divert-crown, crown-smooth, divert-gkeys, m-key-leds, mr-key-led, multiplatform, change-host, gesture2-gestures,
    gesture2-divert, gesture2-params, lowres-scroll-mode, hires-scroll-mode, sidetone, equalizer]
  _modelId: '000000000000'
  _serial: 0F193031
  _unitId: '00000000'
  _wpid: '4003'
- _NAME: Wireless Mouse MX Master 2S
  _modelId: B01E40710000
  _serial: 37BB0FCA
  _unitId: 20FCEF34
  _wpid: '4069'
  divert-keys: {82: 0, 83: 0, 86: 0, 195: 0, 196: 0, 215: 0}
  dpi: 1000
  dpi-sliding: 0
  gesture2-gestures: {45: true, 46: true}
  hires-smooth-invert: false
  hires-smooth-resolution: true
  mouse-gestures: 0
  reprogrammable-keys: {80: 80, 81: 81, 82: 82, 83: 83, 86: 86, 195: 195, 196: 196}
  smart-shift: 16
- _NAME: Wireless Mouse MX Master 2S
  _absent: [hi-res-scroll, lowres-smooth-scroll, thumb-scroll-mode, thumb-scroll-invert, onboard_profiles, report_rate, pointer_speed, speed-change, backlight,
    backlight-timed, fn-swap, persistent-remappable-keys, disable-keyboard-keys, divert-crown, crown-smooth, divert-gkeys, m-key-leds, mr-key-led, multiplatform,
    gesture2-params, lowres-scroll-mode, sidetone, equalizer]
  _battery: 4096
  _modelId: B01940690000
  _sensitive: {divert-keys: false, dpi: false, gesture2-gestures: false, hires-smooth-invert: false, hires-smooth-resolution: false, mouse-gestures: false,
    reprogrammable-keys: false, smart-shift: false}
  _serial: DB37EDED
  _unitId: 127BEBDC
  _wpid: '4069'
  change-host: null
  divert-keys: {82: 0, 83: 0, 86: 0, 195: 1, 196: 1, 215: 0, '0': 2}
  dpi: '2500'
  dpi-sliding: 0
  gesture2-divert: {46: false}
  gesture2-gestures: {45: true, 46: true}
  hires-scroll-mode: false
  hires-smooth-invert: false
  hires-smooth-resolution: true
  reprogrammable-keys: {80: 80, 81: 81, 82: 82, 83: 83, 86: 86, 195: 195, 196: 196}
  smart-shift: 12
- _NAME: Wireless Keyboard K375s
  _absent: [hi-res-scroll, lowres-scroll-mode, hires-smooth-invert, hires-smooth-resolution, hires-scroll-mode, smart-shift, thumb-scroll-invert, thumb-scroll-mode,
    onboard_profiles, report_rate, pointer_speed, dpi, dpi-sliding, speed-change, mouse-gestures, backlight, backlight-timed, reprogrammable-keys, crown-smooth,
    divert-crown, divert-gkeys, m-key-leds, mr-key-led, gesture2-gestures, gesture2-divert, gesture2-params, sidetone, equalizer]
  _modelId: B34C40610000
  _serial: 9AE82DDC
  _unitId: DB5BB00B
  _wpid: '4061'
  change-host: null
  disable-keyboard-keys: {1: false, 2: false, 4: false, 8: false, 16: false}
  divert-keys: {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 10: 0, 189: 0, 191: 0, 192: 0, 193: 0, 209: 0, 210: 0, 211: 0, 212: 0, 213: 0, 214: 0, 221: 0}
  fn-swap: true
  multiplatform: 0
  persistent-remappable-keys: null
- {_NAME: MX Master 3 Wireless Mouse, _serial: FDAE16EE, _wpid: '4082'}
- _NAME: Wireless Keyboard K375s
  _absent: [hi-res-scroll, lowres-scroll-mode, hires-smooth-invert, hires-smooth-resolution, hires-scroll-mode, smart-shift, thumb-scroll-invert, thumb-scroll-mode,
    onboard_profiles, report_rate, pointer_speed, dpi, dpi-sliding, speed-change, mouse-gestures, backlight, backlight-timed, reprogrammable-keys, crown-smooth,
    divert-crown, divert-gkeys, m-key-leds, mr-key-led, gesture2-gestures, gesture2-divert, gesture2-params, sidetone, equalizer]
  _battery: 4096
  _modelId: B34C40610000
  _sensitive: {disable-keyboard-keys: false, divert-keys: false, fn-swap: false, multiplatform: false, persistent-remappable-keys: false}
  _serial: B70E1D61
  _unitId: 6CFA7C3F
  _wpid: '4061'
  change-host: null
  disable-keyboard-keys: {1: false, 2: false, 4: true, 8: false, 16: false}
  divert-keys: {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 10: 0, 189: 0, 191: 0, 192: 0, 193: 0, 209: 0, 210: 0, 211: 0, 212: 0, 213: 0, 214: 0, 221: 0}
  fn-swap: false
  multiplatform: 0
  persistent-remappable-keys: null

```

</details>


Discussion:

Resolving patch:
diff --git a/lib/logitech_receiver/settings.py b/lib/logitech_receiver/settings.py
--- a/lib/logitech_receiver/settings.py
+++ b/lib/logitech_receiver/settings.py
@@ -1448,12 +1448,13 @@ def handler(self, device, n):  # Called on notification events from the device
 
     def start(self, key):
         device_key = next((k for k in self.device.keys if k.key == key), None)
-        self.keys.append(device_key)
-        if not self.active:
-            self.active = True
-            self.activate_action()
-            self.device.add_notification_handler(self.name, self.handler)
-        device_key.set_rawXY_reporting(True)
+        if device_key:
+            self.keys.append(device_key)
+            if not self.active:
+                self.active = True
+                self.activate_action()
+                self.device.add_notification_handler(self.name, self.handler)
+            device_key.set_rawXY_reporting(True)
 
     def stop(self, key):  # only stop if this is the active key
         if self.active:
diff --git a/lib/logitech_receiver/special_keys.py b/lib/logitech_receiver/special_keys.py
--- a/lib/logitech_receiver/special_keys.py
+++ b/lib/logitech_receiver/special_keys.py
@@ -302,6 +302,8 @@
     'Standard_Key_A': 0x122,
     'Standard_Key_B': 0x123,
     'Standard_Key_C': 0x124,  # There are lots more of these
+    'Right_Option__Start__2': 0x013C,  # On MX Mechanical Mini
+    'Play_Pause': 0x0141,  # On MX Mechanical Mini
 })
 
 for i in range(1, 33):  # add in G keys - these are not really Logitech Controls


Test patch: