diff --git a/Manual.org b/Manual.org index eb28770..39bbe3a 100644 --- a/Manual.org +++ b/Manual.org @@ -3145,13 +3145,13 @@ If a Sat>IP Server responds to a discovery request, the package vdr-plugin-satip action: satip_facts - debug: - var: satip_detected + var: satip_devices verbosity: 1 - name: apt | install vdr-plugin-satip if a Sat>IP server has been detected apt: name: vdr-plugin-satip - when: satip_detected + when: satip_devices notify: [ 'Restart VDR' ] #+END_SRC @@ -3164,8 +3164,7 @@ If a Sat>IP Server responds to a discovery request, the package vdr-plugin-satip - name: apt | install vdr-plugin-targavfd if connected apt: name: vdr-plugin-targavfd - when: - - "19c2:6a11" in usb + when: '"19c2:6a11" in usb' notify: [ 'Restart VDR' ] #+END_SRC ** autoinstall-imonlcd @@ -3177,9 +3176,7 @@ If a Sat>IP Server responds to a discovery request, the package vdr-plugin-satip - name: apt | install vdr-plugin-imonlcd if connected apt: name: vdr-plugin-imonlcd - when: - - "15c2:0038" in usb - - "15c2:ffdc" in usb + when: '"15c2:0038" in usb or "15c2:ffdc" in usb' notify: [ 'Restart VDR' ] #+END_SRC ** autoinstall-libcecdaemon @@ -3203,8 +3200,7 @@ If a Sat>IP Server responds to a discovery request, the package vdr-plugin-satip - name: apt | install vdr-plugin-pvr350 if connected apt: name: vdr-plugin-pvr350 - when: - - "0070:4000" in pci + when: '"0070:4000" in pci' notify: [ 'Restart VDR' ] #+END_SRC ** autoinstall-hauppauge-pvr @@ -3215,9 +3211,7 @@ If a Sat>IP Server responds to a discovery request, the package vdr-plugin-satip - name: apt | install vdr-plugin-pvrinput if a haupauge pvr card is found apt: name: vdr-plugin-pvrinput - when: - - "0070:4000" in pci - - "4444:0016" in pci + when: '"0070:4000" in pci or "4444:0016" in pci' notify: [ 'Restart VDR' ] #+END_SRC ** TODO autoinstall-dvbhddevice @@ -3230,9 +3224,7 @@ Problem: woher kommt der Treiber (AFAIK noch nicht im Kernel)? Die Firmware soll - name: apt | install vdr-plugin-dvbhddevice if connected apt: name: vdr-plugin-dvbhddevice - when: - - '"13c2:300a" in pci' - - '"13c2:300b" in pci' + when: '"13c2:300a" in pci or "13c2:300b" in pci' notify: [ 'Restart VDR' ] #+END_SRC @@ -3245,8 +3237,7 @@ Problem: woher kommt der Treiber (AFAIK noch nicht im Kernel)? Die Firmware soll - name: apt | install vdr-plugin-dvbsddevice if module is loaded apt: name: vdr-plugin-dvbsddevice - when: - - '"dvb_ttpci" in modules' + when: '"dvb_ttpci" in modules' notify: [ 'Restart VDR' ] #+END_SRC ** kodi @@ -4401,23 +4392,26 @@ module: hardware_facts short_description: "check if at least one SAT>IP server responds on the network" description: - This script sends a multicast message and awaits responses by Sat>IP servers. - Returns the boolean variable 'satip_detected' + Returns a list of detected SAT>IP servers with their name and capabilites. ''' EXAMPLES = ''' - name: "detect SAT>IP Server on the network" action: satip_facts - debug: - var: satip_detected + var: satip_devices ''' import json import socket import sys import time - +import xml.etree.ElementTree as ET +import requests +from contextlib import contextmanager from ansible.module_utils.basic import * +SSDP_BIND = "0.0.0.0" SSDP_ADDR = "239.255.255.250" SSDP_PORT = 1900 # SSDP_MX = max delay for server response @@ -4433,28 +4427,81 @@ ssdpRequest = "\r\n".join(( "ST: %s" % (SSDP_ST), "\r\n")) -def main(): - module = AnsibleModule(argument_spec={}, supports_check_mode=True,) - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - # according to Sat>IP Specification 1.2.2, p. 20 - # a client should send three requests within 100 ms with a ttl of 2 +@contextmanager +def socket_manager(*args, **kwargs): + """provide a context manager for socket""" + sock = socket.socket(*args, **kwargs) + sock.setblocking(False) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) - sock.settimeout(SSDP_MX + 0.5) - for _ in range(3): - sock.sendto(ssdpRequest, (SSDP_ADDR, SSDP_PORT)) - time.sleep(0.03) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: - response = sock.recv(1000) - if response and "SERVER:" in response: - got_response = True - else: - raise ValueError('No satip server detected') - except (socket.timeout, ValueError): - got_response = False + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + except socket.error: + pass + sock.settimeout(SSDP_MX + 0.5) + sock.bind((SSDP_BIND, SSDP_PORT)) + try: + yield sock + finally: + sock.close() - module.exit_json(changed=False, ansible_facts={'satip_detected': got_response}) -if __name__ == '__main__': +def parse_satip_xml(data): + """ Parse SAT>IP XML data. + Args: + data (str): XML input data.. + Returns: + dict: Parsed SAT>IP device name and frontend information. + """ + result = {'name': '', 'frontends': {}} + if data: + root = ET.fromstring(data) + name = root.find('.//*/{urn:schemas-upnp-org:device-1-0}friendlyName') + result['name'] = name.text + satipcap = root.find('.//*/{urn:ses-com:satip}X_SATIPCAP') + if satipcap is None: + raise ValueError("Invalid SAT>IP device description") + caps = {} + for system in satipcap.text.split(","): + cap = system.split("-") + if cap: + count = int(cap[1]) + if cap[0] in caps: + count = count + caps[cap[0]] + caps[cap[0]] = count + result['frontends'] = caps + return result + + +def main(): + description_urls = [] + device_list = [] + module = AnsibleModule(argument_spec={}, supports_check_mode=True,) + with socket_manager(socket.AF_INET, socket.SOCK_DGRAM) as sock: + # according to Sat>IP Specification 1.2.2, p. 20 + # a client should send three requests within 100 ms with a ttl of 2 + + for _ in range(3): + sock.sendto(ssdpRequest, (SSDP_ADDR, SSDP_PORT)) + time.sleep(0.03) + try: + response = sock.recv(1024) + if response and "SERVER:" in response: + for line in response.splitlines(): + if "LOCATION" in line: + url = line.split()[-1].strip() + if url not in description_urls: + description_urls.append(url) + info = requests.get(url, timeout=2) + device_list.append(parse_satip_xml(info.text)) + else: + raise ValueError('No satip server detected') + except (socket.timeout, ValueError, ET.ParseError): + pass + + module.exit_json(changed=False, ansible_facts={'satip_devices': device_list}) + +if __name__ == '__main__': main() #+END_SRC ** xrandr_facts.py diff --git a/library/satip_facts.py b/library/satip_facts.py index 6fe23a9..84b726b 100755 --- a/library/satip_facts.py +++ b/library/satip_facts.py @@ -5,23 +5,26 @@ module: hardware_facts short_description: "check if at least one SAT>IP server responds on the network" description: - This script sends a multicast message and awaits responses by Sat>IP servers. - Returns the boolean variable 'satip_detected' + Returns a list of detected SAT>IP servers with their name and capabilites. ''' EXAMPLES = ''' - name: "detect SAT>IP Server on the network" action: satip_facts - debug: - var: satip_detected + var: satip_devices ''' import json import socket import sys import time - +import xml.etree.ElementTree as ET +import requests +from contextlib import contextmanager from ansible.module_utils.basic import * +SSDP_BIND = "0.0.0.0" SSDP_ADDR = "239.255.255.250" SSDP_PORT = 1900 # SSDP_MX = max delay for server response @@ -37,26 +40,79 @@ ssdpRequest = "\r\n".join(( "ST: %s" % (SSDP_ST), "\r\n")) -def main(): - module = AnsibleModule(argument_spec={}, supports_check_mode=True,) - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - # according to Sat>IP Specification 1.2.2, p. 20 - # a client should send three requests within 100 ms with a ttl of 2 +@contextmanager +def socket_manager(*args, **kwargs): + """provide a context manager for socket""" + sock = socket.socket(*args, **kwargs) + sock.setblocking(False) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) - sock.settimeout(SSDP_MX + 0.5) - for _ in range(3): - sock.sendto(ssdpRequest, (SSDP_ADDR, SSDP_PORT)) - time.sleep(0.03) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: - response = sock.recv(1000) - if response and "SERVER:" in response: - got_response = True - else: - raise ValueError('No satip server detected') - except (socket.timeout, ValueError): - got_response = False + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + except socket.error: + pass + sock.settimeout(SSDP_MX + 0.5) + sock.bind((SSDP_BIND, SSDP_PORT)) + try: + yield sock + finally: + sock.close() - module.exit_json(changed=False, ansible_facts={'satip_detected': got_response}) -if __name__ == '__main__': +def parse_satip_xml(data): + """ Parse SAT>IP XML data. + Args: + data (str): XML input data.. + Returns: + dict: Parsed SAT>IP device name and frontend information. + """ + result = {'name': '', 'frontends': {}} + if data: + root = ET.fromstring(data) + name = root.find('.//*/{urn:schemas-upnp-org:device-1-0}friendlyName') + result['name'] = name.text + satipcap = root.find('.//*/{urn:ses-com:satip}X_SATIPCAP') + if satipcap is None: + raise ValueError("Invalid SAT>IP device description") + caps = {} + for system in satipcap.text.split(","): + cap = system.split("-") + if cap: + count = int(cap[1]) + if cap[0] in caps: + count = count + caps[cap[0]] + caps[cap[0]] = count + result['frontends'] = caps + return result + + +def main(): + description_urls = [] + device_list = [] + module = AnsibleModule(argument_spec={}, supports_check_mode=True,) + with socket_manager(socket.AF_INET, socket.SOCK_DGRAM) as sock: + # according to Sat>IP Specification 1.2.2, p. 20 + # a client should send three requests within 100 ms with a ttl of 2 + + for _ in range(3): + sock.sendto(ssdpRequest, (SSDP_ADDR, SSDP_PORT)) + time.sleep(0.03) + try: + response = sock.recv(1024) + if response and "SERVER:" in response: + for line in response.splitlines(): + if "LOCATION" in line: + url = line.split()[-1].strip() + if url not in description_urls: + description_urls.append(url) + info = requests.get(url, timeout=2) + device_list.append(parse_satip_xml(info.text)) + else: + raise ValueError('No satip server detected') + except (socket.timeout, ValueError, ET.ParseError): + pass + + module.exit_json(changed=False, ansible_facts={'satip_devices': device_list}) + +if __name__ == '__main__': main() diff --git a/roles/autoinstall-dvbhddevice/tasks/main.yml b/roles/autoinstall-dvbhddevice/tasks/main.yml index 0c6bb22..72938d7 100644 --- a/roles/autoinstall-dvbhddevice/tasks/main.yml +++ b/roles/autoinstall-dvbhddevice/tasks/main.yml @@ -4,7 +4,5 @@ - name: apt | install vdr-plugin-dvbhddevice if connected apt: name: vdr-plugin-dvbhddevice - when: - - '"13c2:300a" in pci' - - '"13c2:300b" in pci' + when: '"13c2:300a" in pci or "13c2:300b" in pci' notify: [ 'Restart VDR' ] diff --git a/roles/autoinstall-dvbsddevice/tasks/main.yml b/roles/autoinstall-dvbsddevice/tasks/main.yml index 78a7243..1bf9b32 100644 --- a/roles/autoinstall-dvbsddevice/tasks/main.yml +++ b/roles/autoinstall-dvbsddevice/tasks/main.yml @@ -4,6 +4,5 @@ - name: apt | install vdr-plugin-dvbsddevice if module is loaded apt: name: vdr-plugin-dvbsddevice - when: - - '"dvb_ttpci" in modules' + when: '"dvb_ttpci" in modules' notify: [ 'Restart VDR' ] diff --git a/roles/autoinstall-hauppauge-pvr/tasks/main.yml b/roles/autoinstall-hauppauge-pvr/tasks/main.yml index abbfd02..2cfa520 100644 --- a/roles/autoinstall-hauppauge-pvr/tasks/main.yml +++ b/roles/autoinstall-hauppauge-pvr/tasks/main.yml @@ -4,7 +4,5 @@ - name: apt | install vdr-plugin-pvrinput if a haupauge pvr card is found apt: name: vdr-plugin-pvrinput - when: - - "0070:4000" in pci - - "4444:0016" in pci + when: '"0070:4000" in pci or "4444:0016" in pci' notify: [ 'Restart VDR' ] diff --git a/roles/autoinstall-imonlcd/tasks/main.yml b/roles/autoinstall-imonlcd/tasks/main.yml index 300ec53..0a11634 100644 --- a/roles/autoinstall-imonlcd/tasks/main.yml +++ b/roles/autoinstall-imonlcd/tasks/main.yml @@ -4,7 +4,5 @@ - name: apt | install vdr-plugin-imonlcd if connected apt: name: vdr-plugin-imonlcd - when: - - "15c2:0038" in usb - - "15c2:ffdc" in usb + when: '"15c2:0038" in usb or "15c2:ffdc" in usb' notify: [ 'Restart VDR' ] diff --git a/roles/autoinstall-pvr350/tasks/main.yml b/roles/autoinstall-pvr350/tasks/main.yml index 8eb14de..cc91875 100644 --- a/roles/autoinstall-pvr350/tasks/main.yml +++ b/roles/autoinstall-pvr350/tasks/main.yml @@ -4,6 +4,5 @@ - name: apt | install vdr-plugin-pvr350 if connected apt: name: vdr-plugin-pvr350 - when: - - "0070:4000" in pci + when: '"0070:4000" in pci' notify: [ 'Restart VDR' ] diff --git a/roles/autoinstall-satip/tasks/main.yml b/roles/autoinstall-satip/tasks/main.yml index 9b3733d..4c75584 100644 --- a/roles/autoinstall-satip/tasks/main.yml +++ b/roles/autoinstall-satip/tasks/main.yml @@ -5,11 +5,11 @@ action: satip_facts - debug: - var: satip_detected + var: satip_devices verbosity: 1 - name: apt | install vdr-plugin-satip if a Sat>IP server has been detected apt: name: vdr-plugin-satip - when: satip_detected + when: satip_devices notify: [ 'Restart VDR' ] diff --git a/roles/autoinstall-targavfd/tasks/main.yml b/roles/autoinstall-targavfd/tasks/main.yml index 5385e86..af0613b 100644 --- a/roles/autoinstall-targavfd/tasks/main.yml +++ b/roles/autoinstall-targavfd/tasks/main.yml @@ -4,6 +4,5 @@ - name: apt | install vdr-plugin-targavfd if connected apt: name: vdr-plugin-targavfd - when: - - "19c2:6a11" in usb + when: '"19c2:6a11" in usb' notify: [ 'Restart VDR' ]