Esempio n. 1
0
class Receiver(object):
    def __init__(self):
        self.registered = False
        self.intentName = ''
        self.actionName = ''

    def register(self, intentName, actionName, callback):
        self.br = BroadcastReceiver(self.on_broadcast,
                                    actions=[intentName + actionName])
        self.intentName = intentName
        self.actionName = actionName
        self.callback = callback
        self.registered = True

    def stop(self):
        if self.registered:
            self.br.stop()

    def start(self):
        if self.registered:
            self.br.start()

    def on_broadcast(self, context, intent):
        actionName = self.actionName
        action = intent.getAction()
        if self.intentName + actionName == action:
            self.callback(actionName)
class Receiver:
    def __init__(self):
        self.registered = False
        self.intentName = ''
        self.actionName = ''

    def register(self, intentName, actionName, callback):
        self.br = BroadcastReceiver(self.on_broadcast, actions=[intentName+actionName])
        self.intentName = intentName
        self.actionName = actionName
        self.callback = callback
        self.registered = True

    def stop(self):
        if self.registered:
            self.br.stop()

    def start(self):
        if self.registered:
            self.br.start()

    def on_broadcast(self, context, intent):
        actionName = self.actionName
        action = intent.getAction()
        if self.intentName + actionName == action:
            self.callback(actionName)
Esempio n. 3
0
class MainApp(MDApp):
    def build(self):
        self.title = "Bluetooth Input Reader"
        self.theme_cls.primary_palette = "Pink"
        self.theme_cls.primary_hue = "400"
        self.icon = '/res/images/poolleaf_16619.png'
        self.use_kivy_settings = False
        self.br = None
        self.br_strt = False
        if platform == 'android':
            self.br = BroadcastReceiver(self.on_broadcast, actions=['state_changed'])

    def build_config(self, config):
        config.setdefaults('bluetoothsettings', {
            'optionsbluetuuid': '00001101-0000-1000-8000-00805f9b34fb',
            'optionsbluetencoding': 'LATIN-1'})

    def build_settings(self, settings):
        settings.add_json_panel('Bluetooth Settings',
                                self.config,
                                data=bluetooth_settings_json)
    def on_start(self):
        BluetoothHelper().run()

    def start_broadcats(self):
        if self.br and not self.br_strt:
            self.br.start()
            self.br_strt = True

    def stop_broadcats(self):
        if self.br and self.br_strt:
            self.br.stop()
            self.br_strt = False

    def on_broadcast(self, context, intent):
        listen = intent.getAction()
        state = None
        if listen == BluetoothAdapter.ACTION_STATE_CHANGED:
            state = intent.getIntExtra(
                BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
        if state == BluetoothAdapter.STATE_ON:
            self.root.ids.is_bluetooth.text = 'ON'
            self.root.get_devices()
        elif BluetoothAdapter.STATE_OFF:
            self.root.ids.is_bluetooth.text = 'OFF'
    def on_pause(self):
        self.stop_broadcats()
        self.root.cancel_scale()
        return True

    def on_stop(self):
        self.stop_broadcats()
        self.root.cancel_scale()
        return True

    def on_resume(self):
        self.br = BroadcastReceiver(self.on_broadcast, actions=['state_changed'])
        self.start_broadcats()
        return True
Esempio n. 4
0
class CurrentGameScreen(Screen, FloatLayout):
    def __init__ (self, *args, **kwargs):
        super(CurrentGameScreen, self).__init__(*args, **kwargs)
        self.eliminate = self.ids['eliminate']
        self.status = self.ids['status']
        self.eliminate.disabled = True
        self.BluetoothAdapter = autoclass('android.bluetooth.BluetoothAdapter')
        self.BluetoothDevice = autoclass('android.bluetooth.BluetoothDevice')
        self.BluetoothSocket = autoclass('android.bluetooth.BluetoothSocket')
        self.UUID = autoclass('java.util.UUID')
        self.Bundle = autoclass('android.os.Bundle')
        self.Intent = autoclass('android.content.Intent')
        self.IntentFilter = autoclass('android.content.IntentFilter')
        self.Context = autoclass('android.content.Context')
        self.Toast = autoclass('android.widget.Toast')
        self.PythonActivity = autoclass('org.renpy.android.PythonActivity')

        self.myBTA = self.BluetoothAdapter.getDefaultAdapter()
        self.popup = Popup(title='Notification', content=Label(text='Searching For Target. . .'), size_hint=(.9, .3), size=(800, 800))
        self.popup1 = Popup(title='Notification', content=Label(text='Target Found!'), size_hint=(.9, .3), size=(800, 800))


    def goback(self):
        sm.current = "Home"

    def findTarget(self):
        self.popup.open()
        self.br = BroadcastReceiver(self.onReceive, actions=['main'], myFilter = self.BluetoothDevice.ACTION_FOUND)
        self.br.start()
        self.myBTA.startDiscovery()

    def onReceive(self, context, intent):
        action = intent.getAction();
        if (self.BluetoothDevice.ACTION_FOUND == action):
            extras = intent.getParcelableExtra(self.BluetoothDevice.EXTRA_DEVICE)
            device = cast('android.bluetooth.BluetoothDevice', extras)
            deviceName = device.getAddress()
            if deviceName == user.target:
                self.eliminate.disabled = False
                self.eliminate.color = (1,0,0,1)
                self.popup.dismiss()
                self.popup1.open()
                self.br.stop()

    def eliminateUser(self):
        query = retrieve("SELECT target FROM users WHERE bt_ID = '%s'" % (user.target))
        update("UPDATE users SET target = '',status = '0' WHERE bt_ID = '%s'" % (user.target))
        user.target = query[0]
        print user.target, '**************************************'
        create("UPDATE users SET target = '%s' WHERE uid = '%s'" % (user.target, user.uid))
        updateUser()
        query1 = retrieve("SELECT firstname,lastname FROM users WHERE bt_ID = '%s'" % (user.target))
        tfirstname, tlastname = query1[0]
        self.status.text = str("Your Current Target is %s %s" % (tfirstname, tlastname))
Esempio n. 5
0
class DeviceManagerService(object):
    def __init__(self, **kwargs):
        self.debug_params = dict()
        self.addit_params = dict()
        for key, val in kwargs.items():
            mo = re.search('^debug_([^_]+)_(.+)', key)
            if mo:
                kk = mo.group(1)
                ll = self.debug_params.get(kk, dict())
                ll[mo.group(2)] = val
                self.debug_params[kk] = ll
            elif key.startswith('ab_'):
                self.addit_params[key[3:]] = val
            else:
                setattr(self, key, val)
        _LOGGER.debug(
            f'Addit params for DM {self.addit_params} AND {self.debug_params}')
        self.db = None
        self.oscer = None
        self.notification_formatter_info = dict()
        self.connectors_format = False
        self.devicemanager_class_by_type = dict()
        self.devicemanagers_pre_actions = dict()
        self.devicemanagers_by_id = dict()
        self.devicemanagers_by_uid = dict()
        self.connectors_info = []
        self.users = []
        self.views = []
        self.devices = []
        self.devicemanagers_active = []
        self.devicemanagers_active_done = []
        self.timer_obj = None
        self.main_session = None
        self.last_user = None
        self.devicemanagers_active_info = dict()
        self.stop_event = asyncio.Event()
        self.last_notify_ms = time() * 1000
        if self.android:
            from jnius import autoclass
            from android.broadcast import BroadcastReceiver
            self.Context = autoclass('android.content.Context')
            self.AndroidString = autoclass('java.lang.String')
            self.NotificationCompatInboxStyle = autoclass(
                'android.app.Notification$InboxStyle')
            NotificationBuilder = autoclass('android.app.Notification$Builder')
            self.PythonActivity = autoclass('org.kivy.android.PythonActivity')
            self.service = autoclass('org.kivy.android.PythonService').mService
            NOTIFICATION_CHANNEL_ID = self.AndroidString(
                self.service.getPackageName().encode('utf-8'))
            self.NOTIFICATION_GROUP = 'pyMovizGroup'
            self.FOREGROUND_NOTIFICATION_ID = 4563
            app_context = self.service.getApplication().getApplicationContext()
            self.app_context = app_context
            self.notification_service = self.service.getSystemService(
                self.Context.NOTIFICATION_SERVICE)
            self.CONNECT_ACTION = 'device_manager_service.view.CONNECT'
            self.DISCONNECT_ACTION = 'device_manager_service.view.DISCONNECT'
            self.STOP_ACTION = 'device_manager_service.STOP'

            self.br = BroadcastReceiver(self.on_broadcast,
                                        actions=[
                                            self.CONNECT_ACTION,
                                            PRESENCE_REQUEST_ACTION,
                                            self.DISCONNECT_ACTION,
                                            self.STOP_ACTION
                                        ])
            self.br.start()

            Intent = autoclass('android.content.Intent')
            self.Intent = Intent
            PendingIntent = autoclass('android.app.PendingIntent')
            NotificationActionBuilder = autoclass(
                'android.app.Notification$Action$Builder')
            Notification = autoclass('android.app.Notification')
            Color = autoclass("android.graphics.Color")
            NotificationChannel = autoclass('android.app.NotificationChannel')
            NotificationManager = autoclass('android.app.NotificationManager')
            channelName = self.AndroidString(
                'DeviceManagerService'.encode('utf-8'))
            chan = NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,
                                       NotificationManager.IMPORTANCE_DEFAULT)
            chan.setLightColor(Color.BLUE)
            chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE)
            self.notification_service.createNotificationChannel(chan)
            BitmapFactory = autoclass("android.graphics.BitmapFactory")
            Icon = autoclass("android.graphics.drawable.Icon")
            BitmapFactoryOptions = autoclass(
                "android.graphics.BitmapFactory$Options")
            # Drawable = jnius.autoclass("{}.R$drawable".format(service.getPackageName()))
            # icon = getattr(Drawable, 'icon')
            options = BitmapFactoryOptions()
            # options.inMutable = True
            # declaredField = options.getClass().getDeclaredField("inPreferredConfig")
            # declaredField.set(cast('java.lang.Object',options), cast('java.lang.Object', BitmapConfig.ARGB_8888))
            # options.inPreferredConfig = BitmapConfig.ARGB_8888;
            notification_image = join(dirname(__file__), '..', 'images',
                                      'device_manager.png')
            bm = BitmapFactory.decodeFile(notification_image, options)
            notification_icon = Icon.createWithBitmap(bm)

            notification_image = join(dirname(__file__), '..', 'images',
                                      'lan-connect.png')
            bm = BitmapFactory.decodeFile(notification_image, options)
            icon = Icon.createWithBitmap(bm)
            broadcastIntent = Intent(self.CONNECT_ACTION)
            actionIntent = PendingIntent.getBroadcast(
                self.service, 0, broadcastIntent,
                PendingIntent.FLAG_UPDATE_CURRENT)
            connect_action = NotificationActionBuilder(
                icon, self.AndroidString('CONNECT'.encode('utf-8')),
                actionIntent).build()

            notification_image = join(dirname(__file__), '..', 'images',
                                      'lan-disconnect.png')
            bm = BitmapFactory.decodeFile(notification_image, options)
            icon = Icon.createWithBitmap(bm)
            broadcastIntent = Intent(self.DISCONNECT_ACTION)
            actionIntent = PendingIntent.getBroadcast(
                self.service, 0, broadcastIntent,
                PendingIntent.FLAG_UPDATE_CURRENT)
            disconnect_action = NotificationActionBuilder(
                icon, self.AndroidString('DISCONNECT'.encode('utf-8')),
                actionIntent).build()

            notification_image = join(dirname(__file__), '..', 'images',
                                      'stop.png')
            bm = BitmapFactory.decodeFile(notification_image, options)
            icon = Icon.createWithBitmap(bm)
            broadcastIntent = Intent(self.STOP_ACTION)
            actionIntent = PendingIntent.getBroadcast(
                self.service, 0, broadcastIntent,
                PendingIntent.FLAG_UPDATE_CURRENT)
            stop_action = NotificationActionBuilder(
                icon, self.AndroidString('STOP'.encode('utf-8')),
                actionIntent).build()

            notification_intent = Intent(app_context, self.PythonActivity)
            notification_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                                         | Intent.FLAG_ACTIVITY_SINGLE_TOP
                                         | Intent.FLAG_ACTIVITY_NEW_TASK)
            notification_intent.setAction(Intent.ACTION_MAIN)
            notification_intent.addCategory(Intent.CATEGORY_LAUNCHER)
            notification_intent = PendingIntent.getActivity(
                self.service, 0, notification_intent, 0)
            self.notification_builder = NotificationBuilder(app_context, NOTIFICATION_CHANNEL_ID)\
                .setContentIntent(notification_intent)\
                .setSmallIcon(notification_icon)\
                .addAction(connect_action)\
                .addAction(disconnect_action)\
                .addAction(stop_action)
            self.notification_builder_no_action = NotificationBuilder(app_context, NOTIFICATION_CHANNEL_ID)\
                .setContentIntent(notification_intent)\
                .setSmallIcon(notification_icon)

    def on_broadcast(self, context, intent):
        action = intent.getAction()
        _LOGGER.info(f'on_broadcast action {action}')
        if action == self.CONNECT_ACTION:
            self.loop.call_soon_threadsafe(self.on_command_condisc, 'c',
                                           self.last_user)
        elif action == self.DISCONNECT_ACTION:
            self.loop.call_soon_threadsafe(self.on_command_condisc, 'd')
        elif action == PRESENCE_REQUEST_ACTION:
            self.app_context.sendBroadcast(
                self.Intent(PRESENCE_RESPONSE_ACTION))
        else:
            self.loop.call_soon_threadsafe(self.on_command_stop)

    def change_service_notification(self, dm, **kwargs):
        if self.android:
            alias = dm.get_device().get_alias()
            if alias not in self.notification_formatter_info:
                idnot = self.FOREGROUND_NOTIFICATION_ID + len(
                    self.notification_formatter_info)
                self.notification_formatter_info[alias] =\
                    DeviceNotiication(dm,
                                      idnot,
                                      self)
            self.notification_formatter_info[alias].format(**kwargs)

    async def init_osc(self):
        self.oscer = OSCManager(hostlisten=self.hostlisten,
                                portlisten=self.portlisten)
        await self.oscer.init(on_init_ok=self.on_osc_init_ok)

    def on_osc_init_ok(self, exception=None):
        if not exception:
            self.oscer.handle(COMMAND_STOP, self.on_command_stop)
            self.oscer.handle(COMMAND_LOGLEVEL, self.on_command_loglevel)
            self.oscer.handle(COMMAND_NEWDEVICE, self.on_command_newdevice)
            self.oscer.handle(COMMAND_QUERY,
                              self.on_command_query,
                              do_split=True)
            self.oscer.handle(COMMAND_CONNECT, self.on_command_condisc, 'c')
            self.oscer.handle(COMMAND_DISCONNECT, self.on_command_condisc, 'd')
            self.oscer.handle(COMMAND_CONNECTORS, self.on_command_connectors)
            self.oscer.handle(COMMAND_LISTDEVICES, self.on_command_listdevices)
            self.oscer.handle(COMMAND_LISTUSERS, self.on_command_listusers)
            self.oscer.handle(COMMAND_LISTVIEWS, self.on_command_listviews)
            self.oscer.handle(
                COMMAND_SAVEVIEW,
                partial(self.on_command_dbelem,
                        asyncmethod=self.on_command_saveelem_async,
                        lst=self.views,
                        cls=View,
                        on_ok=self.set_devicemanagers_active))
            self.oscer.handle(
                COMMAND_DELVIEW,
                partial(self.on_command_dbelem,
                        asyncmethod=self.on_command_delelem_async,
                        lst=self.views,
                        cls=View,
                        on_ok=self.set_devicemanagers_active))
            self.oscer.handle(
                COMMAND_SAVEUSER,
                partial(self.on_command_dbelem,
                        asyncmethod=self.on_command_saveelem_async,
                        lst=self.users,
                        cls=User))
            self.oscer.handle(
                COMMAND_DELUSER,
                partial(self.on_command_dbelem,
                        asyncmethod=self.on_command_delelem_async,
                        lst=self.users,
                        cls=User))
            self.create_device_managers()

    def on_command_condisc(self, cmd, *args, sender=None, **kwargs):
        _LOGGER.info(f'On Command condisc: {cmd}')
        if cmd == 'c':
            if args and isinstance(args[0], User) and args[0] in self.users:
                self.last_user = args[0]
            else:
                self.oscer.send(COMMAND_CONFIRM,
                                CONFIRM_FAILED_1,
                                MSG_INVALID_USER,
                                dest=sender)
                return
        self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, cmd, dest=sender)
        for dm in self.devicemanagers_active_done.copy():
            self.devicemanagers_active.append(dm)
            self.devicemanagers_active_done.remove(dm)
        from device.manager import GenericDeviceManager
        GenericDeviceManager.sort(self.devicemanagers_active)
        for _, info in self.devicemanagers_active_info.items():
            info['operation'] = cmd
            info['retry'] = 0
        Timer(
            0,
            partial(self.start_remaining_connection_operations, bytimer=False))

    def on_command_listviews(self, *args, sender=None, **kwargs):
        _LOGGER.info('List view before send:')
        for v in self.views:
            _LOGGER.info(f'View = {v}')
        self.oscer.send(COMMAND_LISTVIEWS_RV, *self.views, dest=sender)

    def on_command_listusers(self, *args, sender=None, **kwargs):
        self.oscer.send(COMMAND_LISTUSERS_RV, *self.users, dest=sender)

    def on_command_connectors(self,
                              connectors_info,
                              *args,
                              sender=None,
                              **kwargs):
        connectors_info = json.loads(connectors_info)
        if connectors_info:
            for ci in connectors_info:
                if not exists(ci['temp']):
                    self.oscer.send(COMMAND_CONFIRM,
                                    CONFIRM_FAILED_1,
                                    dest=sender)
                    return
            self.connectors_format = True
            Timer(
                0,
                partial(TcpClient.init_connectors_async, self.loop,
                        connectors_info))
        self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, dest=sender)

    def on_command_listdevices(self, *args, sender=None, **kwargs):
        out = []
        for uid, dm in self.devicemanagers_by_uid.items():
            out.append(uid)
            out.append(dm.get_device())
        self.oscer.send(COMMAND_LISTDEVICES_RV, *out, dest=sender)

    async def on_command_delelem_async(self,
                                       elem,
                                       *args,
                                       lst=None,
                                       on_ok=None,
                                       sender=None,
                                       **kwargs):
        try:
            _LOGGER.info(f'on_command_delelem_async {elem}')
            rv = await elem.delete(self.db)
            if rv:
                if elem in lst:
                    lst.remove(elem)
                self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, elem, dest=sender)
                if on_ok:
                    on_ok(elem)
                TcpClient.reset_templates()
            else:
                self.oscer.send(COMMAND_CONFIRM,
                                CONFIRM_FAILED_1,
                                MSG_DB_SAVE_ERROR % str(elem),
                                dest=sender)
        except Exception:
            _LOGGER.error(
                f'on_command_delelem_async exception {traceback.format_exc()}')

    async def on_command_saveelem_async(self,
                                        elem,
                                        *args,
                                        lst=None,
                                        on_ok=None,
                                        sender=None,
                                        **kwargs):
        try:
            _LOGGER.info(f'on_command_saveelem_async {elem}')
            rv = await elem.to_db(self.db)
            if rv:
                if elem not in lst:
                    lst.append(elem)
                else:
                    lst[lst.index(elem)] = elem
                self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, elem, dest=sender)
                if on_ok:
                    on_ok(elem)
                TcpClient.reset_templates()
            else:
                self.oscer.send(COMMAND_CONFIRM,
                                CONFIRM_FAILED_1,
                                MSG_DB_SAVE_ERROR % str(elem),
                                dest=sender)
        except Exception:
            _LOGGER.error(
                f'on_command_saveelem_async exception {traceback.format_exc()}'
            )

    def on_command_dbelem(self,
                          elem,
                          *args,
                          asyncmethod=None,
                          lst=None,
                          cls=None,
                          on_ok=None,
                          sender=None,
                          **kwargs):
        _LOGGER.info(f'on_command_dbelem {elem}')
        if isinstance(elem, cls):
            if self.devicemanagers_all_stopped():
                Timer(0, partial(asyncmethod, elem, lst=lst, on_ok=on_ok))
            else:
                self.oscer.send(COMMAND_CONFIRM,
                                CONFIRM_FAILED_2,
                                MSG_CONNECTION_STATE_INVALID,
                                dest=sender)
        else:
            self.oscer.send(COMMAND_CONFIRM,
                            CONFIRM_FAILED_1,
                            MSG_INVALID_ITEM,
                            dest=sender)

    def on_event_command_handle(self, dm, command, *args):
        _LOGGER.debug(f'On Command Handle dm={dm} comm={command} a={args}')
        exitv = args[0] if args else None
        if command == COMMAND_NEWSESSION and exitv == CONFIRM_OK:
            if self.connectors_format:
                TcpClient.format(dm.get_device(),
                                 manager=dm,
                                 session=args[2],
                                 user=self.last_user)
            self.change_service_notification(dm,
                                             manager=dm,
                                             session=args[2],
                                             user=self.last_user)
            if self.main_session:
                args[1].set_main_session_id(self.main_session.get_id())
            else:
                self.main_session = args[2]
        elif command == COMMAND_DEVICEFIT and exitv == CONFIRM_OK:
            if self.connectors_format:
                TcpClient.format(args[1],
                                 fitobj=args[2],
                                 manager=dm,
                                 device=args[1])
            self.change_service_notification(dm, fitobj=args[2], manager=dm)
        elif command == COMMAND_DELDEVICE and exitv == CONFIRM_OK:
            ids = f'{dm.get_id()}'
            if ids in self.devicemanagers_by_id:
                del self.devicemanagers_by_id[ids]
            ids = dm.get_uid()
            if ids in self.devicemanagers_active_info:
                del self.devicemanagers_active_info[ids]
            if ids in self.devicemanagers_by_uid:
                del self.devicemanagers_by_uid[ids]
            if dm in self.devicemanagers_active:
                self.devicemanagers_active.remove(dm)
            if dm in self.devicemanagers_active_done:
                self.devicemanagers_active_done.remove(dm)
            self.set_formatters_device()
        elif command == COMMAND_SAVEDEVICE and exitv == CONFIRM_OK:
            ids = f'{dm.get_id()}'
            if ids not in self.devicemanagers_by_id:
                self.devicemanagers_by_id[ids] = dm
            TcpClient.reset_templates()
            self.set_formatters_device()
            self.on_command_listviews()
        elif command == COMMAND_SEARCH and exitv == CONFIRM_OK:
            if dm.get_state() != DEVSTATE_SEARCHING:
                if self.devicemanagers_all_stopped():
                    dm.search(True)
            else:
                dm.search(False)

    def generate_uid(self):
        while True:
            uid = OSCManager.generate_uid()
            if uid not in self.devicemanagers_by_uid:
                return uid

    def devicemanagers_all_stopped(self):
        if not self.devicemanagers_active or not self.timer_obj:
            for _, x in self.devicemanagers_by_uid.items():
                if not x.is_stopped_state():
                    return False
            return True
        else:
            return False

    def on_command_newdevice(self, typev, *args, sender=None, **kwargs):
        if typev not in self.devicemanager_class_by_type:
            self.oscer.send(COMMAND_CONFIRM,
                            CONFIRM_FAILED_1,
                            MSG_TYPE_DEVICE_UNKNOWN,
                            dest=sender)
        elif not self.devicemanagers_all_stopped():
            self.oscer.send(COMMAND_CONFIRM,
                            CONFIRM_FAILED_1,
                            MSG_CONNECTION_STATE_INVALID,
                            dest=sender)
        else:
            uid = self.generate_uid()
            self.devicemanagers_by_uid[uid] = self.devicemanager_class_by_type[
                typev](self.oscer,
                       uid,
                       service=True,
                       db=self.db,
                       loop=self.loop,
                       params=self.addit_params,
                       debug_params=self.debug_params.get(typev, dict()),
                       on_command_handle=self.on_event_command_handle,
                       on_state_transition=self.on_event_state_transition)
            self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, uid, dest=sender)

    async def db_query_single(self, txt):
        result = dict(error='',
                      rows=[],
                      cols=[],
                      rowcount=0,
                      changes=0,
                      lastrowid=-1)
        try:
            async with self.db.cursor() as cursor:
                result['changes_before'] = self.db.total_changes
                await cursor.execute(txt)
                lst = result['rows']
                result['rowcount'] = cursor.rowcount
                result['lastrowid'] = cursor.lastrowid
                result['changes_after'] = self.db.total_changes
                async for row in cursor:
                    if not result['cols']:
                        result['cols'] = list(row.keys())
                    item = ''
                    for r in result['cols']:
                        item += f'\t{row[r]}'
                    lst.append(item.strip())
            await self.db.commit()
        except Exception as ex:
            result['error'] = str(ex)
            _LOGGER.error(f'Query Error {traceback.format_exc()}')
        _LOGGER.info(f'Query {txt} result obtained')
        _LOGGER.debug(f'Query result {result}')
        return result

    async def db_query(self, txt, sender=None):
        queries = re.split(r';[\r\n]*', txt)
        results = []
        for q in queries:
            q = q.strip()
            if q:
                r = await self.db_query_single(q)
                results.append(r)
        self.oscer.send(COMMAND_CONFIRM,
                        CONFIRM_OK,
                        results,
                        do_split=True,
                        dest=sender)

    def on_command_query(self, txt, *args, sender=None, **kwargs):
        _LOGGER.debug(f'on_command_query {txt}')
        if not self.db:
            self.oscer.send(COMMAND_CONFIRM,
                            CONFIRM_FAILED_1,
                            MSG_DB_SAVE_ERROR % self.db_fname,
                            do_split=True,
                            dest=sender)
        elif not txt:
            self.oscer.send(COMMAND_CONFIRM,
                            CONFIRM_FAILED_2,
                            MSG_INVALID_PARAM,
                            do_split=True,
                            dest=sender)
        elif self.devicemanagers_all_stopped():
            Timer(0, partial(self.db_query, txt, sender=None))
        else:
            self.oscer.send(COMMAND_CONFIRM,
                            CONFIRM_FAILED_2,
                            MSG_CONNECTION_STATE_INVALID,
                            do_split=True,
                            dest=sender)

    def on_command_loglevel(self,
                            level,
                            notify_screen_on,
                            notify_every_ms,
                            *args,
                            sender=None,
                            **kwargs):
        init_logger(__name__, level)
        self.verbose = level
        if notify_screen_on >= 0:
            self.notify_screen_on = notify_screen_on
        if notify_every_ms >= 0:
            self.notify_every_ms = notify_every_ms

    def on_command_stop(self, *args, sender=None, **kwargs):
        self.loop.stop()

    def reset_service_notifications(self):
        for _, no in self.notification_formatter_info.items():
            no.clear()
            self.cancel_service_notification(no.idnot)
        if len(self.notification_formatter_info) > 1:
            self.cancel_service_notification(self.FOREGROUND_NOTIFICATION_ID -
                                             1)
        self.notification_formatter_info.clear()

    def cancel_service_notification(self, idnot):
        if idnot == self.FOREGROUND_NOTIFICATION_ID:
            self.set_service_notification(idnot,
                                          self.build_service_notification())
        else:
            self.notification_service.cancel(idnot)

    def set_service_notification(self, idnot, notif):
        self.notification_service.notify(idnot, notif)

    def set_summary_notification(self):
        if len(self.notification_formatter_info) > 1:
            summary = ''
            lines = []
            message = f'{len(self.notification_formatter_info)} active devices'
            for t, no in self.notification_formatter_info.items():
                if no.last_txt:
                    lines.append(no.last_txt)
                summary += f' {no.title}'
            if summary and len(lines) > 1:
                summary = summary[1:]
                self.set_service_notification(
                    self.FOREGROUND_NOTIFICATION_ID - 1,
                    self.build_service_notification(summary, message, lines))

    def build_service_notification(self,
                                   title=None,
                                   message=None,
                                   lines=None,
                                   idnot=0):
        group = None
        nb = self.notification_builder
        if not title and not message:
            title = "Fit.py"
            message = "DeviceManagerService"
        elif len(self.notification_formatter_info) > 1:
            nb = self.notification_builder if idnot == self.FOREGROUND_NOTIFICATION_ID else self.notification_builder_no_action
            group = self.NOTIFICATION_GROUP
        title = self.AndroidString((title if title else 'N/A').encode('utf-8'))
        message = self.AndroidString(message.encode('utf-8'))
        nb.setContentTitle(title)\
            .setGroup(group)\
            .setContentText(message)\
            .setOnlyAlertOnce(self.notify_screen_on <= 0)
        if lines is not None:
            style = self.NotificationCompatInboxStyle()\
                .setSummaryText(title)\
                .setBigContentTitle(message)
            for l in lines:
                style.addLine(self.AndroidString(l.encode('utf-8')))
            nb.setStyle(style)\
                .setGroupSummary(True)
        else:
            nb.setStyle(None)\
                .setGroupSummary(False)
        return nb.getNotification()

    def insert_service_notification(self):
        self.service.setAutoRestartService(False)
        self.service.startForeground(self.FOREGROUND_NOTIFICATION_ID,
                                     self.build_service_notification())

    async def start(self):
        if self.android:
            self.insert_service_notification()
        self.devicemanager_class_by_type = find_devicemanager_classes(_LOGGER)
        for tp, cls in self.devicemanager_class_by_type.items():
            if cls.__pre_action__:
                nm = cls.__pre_action__.__name__
                if nm not in self.devicemanagers_pre_actions:
                    self.devicemanagers_pre_actions[nm] = cls.__pre_action__
        await self.init_db(self.db_fname)
        await self.load_db()
        await self.init_osc()

    def set_devicemanagers_active(self, *args, **kwargs):
        del self.devicemanagers_active_done[:]
        del self.devicemanagers_active[:]
        self.devicemanagers_active_info.clear()
        self.reset_service_notifications()
        for v in self.views:
            if v.active:
                for c in v.get_connected_devices():
                    d = self.devicemanagers_by_id[str(c)]
                    if d not in self.devicemanagers_active_done:
                        self.devicemanagers_active_done.append(d)
        for d in self.devicemanagers_active_done:
            self.devicemanagers_active_info[d.get_uid()] = dict(retry=0,
                                                                operation='')

    def set_formatters_device(self):
        views2save = []
        for v in self.views:
            saveview = False
            for i in range(len(v.items) - 1, -1, -1):
                lab = v.items[i]
                ids = str(lab.device)
                if ids in self.devicemanagers_by_id:
                    lab.set_device(self.devicemanagers_by_id[ids].get_device())
                else:
                    del v.items[i]
                    saveview = True
            if saveview:
                views2save.append(v)
        if views2save:
            Timer(0, partial(self.save_modified_views, views2save))

    async def save_modified_views(self, views2save):
        for v in views2save:
            rv = await v.to_db(self.db)
            _LOGGER.info(f'Saving view {v} -> {rv}')
        self.on_command_listviews()

    def create_device_managers(self):
        for d in self.devices:
            uid = self.generate_uid()
            typev = d.get_type()
            if typev in self.devicemanager_class_by_type:
                dm = self.devicemanager_class_by_type[typev](
                    self.oscer,
                    uid,
                    service=True,
                    loop=self.loop,
                    db=self.db,
                    device=d,
                    params=self.addit_params,
                    debug_params=self.debug_params.get(typev, dict()),
                    on_command_handle=self.on_event_command_handle,
                    on_state_transition=self.on_event_state_transition)
                self.devicemanagers_by_id[f'{d.get_id()}'] = dm
                self.devicemanagers_by_uid[uid] = dm
        self.set_devicemanagers_active()
        self.set_formatters_device()

    async def load_db(self):
        try:
            self.users = await User.loadbyid(self.db)
            self.devices = await Device.loadbyid(self.db)
            self.views = await View.load1m(self.db)
            # _LOGGER.debug(f'List view[0] {self.views[0]}')
        except Exception:
            _LOGGER.error(f'Load DB error {traceback.format_exc()}')

    async def start_remaining_connection_operations(self, bytimer=True):
        try:
            _LOGGER.info(f'Starting remaining con timer={bytimer}')
            if bytimer:
                self.timer_obj = None
            elif self.timer_obj:
                self.timer_obj.cancel()
                self.timer_obj = None
            for dm in self.devicemanagers_active.copy():
                info = self.devicemanagers_active_info[dm.get_uid()]
                _LOGGER.info(
                    f'Processing[{dm.get_uid()}] {dm.get_device()} -> {info["operation"]}'
                )
                if info['operation'] == 'd':
                    if dm.get_state() == DEVSTATE_CONNECTING:
                        self.oscer.send(
                            COMMAND_PRINTMSG,
                            MSG_WAITING_FOR_CONNECTING.format(
                                dm.get_device().get_alias()))
                        break
                    elif not dm.is_connected_state():
                        self.devicemanagers_active.remove(dm)
                        self.devicemanagers_active_done.append(dm)
                    else:
                        dm.disconnect()
                        break
                elif info['operation'] == 'c':
                    if dm.is_connected_state():
                        self.devicemanagers_active.remove(dm)
                        self.devicemanagers_active_done.append(dm)
                    elif bytimer:
                        dm.set_user(self.last_user)
                        if dm.connect():
                            break
                        else:
                            self.oscer.send(
                                COMMAND_PRINTMSG,
                                MSG_DEVICE_NOT_STOPPED.format(
                                    dm.get_device().get_alias()))
                    else:
                        if info['retry'] < self.connect_retry:
                            self.timer_obj = Timer(
                                0 if not info['retry'] else self.connect_secs,
                                self.start_remaining_connection_operations)
                            info['retry'] += 1
                            break
                        else:
                            _LOGGER.info(
                                f'Retry FINISH for device[{dm.get_uid()}] {dm.get_device()}'
                            )
        except Exception:
            _LOGGER.error(f'Rem op error {traceback.format_exc()}')

    def set_operation_ended(self, info):
        info['operation'] = ''
        info['retry'] = 0

    def on_event_state_transition(self, dm, oldstate, newstate, reason):
        if self.connectors_format:
            TcpClient.format(dm.get_device(), state=newstate, manager=dm)
        self.change_service_notification(dm, state=newstate, manager=dm)
        uid = dm.get_uid()
        if uid in self.devicemanagers_active_info:  # assenza significa che stiamo facendo una ricerca
            info = self.devicemanagers_active_info[uid]
            from device.manager import GenericDeviceManager
            if GenericDeviceManager.is_connected_state_s(
                    newstate) and oldstate == DEVSTATE_CONNECTING:
                if info['operation'] == 'c':
                    if dm in self.devicemanagers_active:
                        self.devicemanagers_active.remove(dm)
                        self.devicemanagers_active_done.append(dm)
                    self.set_operation_ended(info)
                Timer(
                    0,
                    partial(self.start_remaining_connection_operations,
                            bytimer=False))
            elif oldstate == DEVSTATE_CONNECTING and newstate == DEVSTATE_DISCONNECTED:
                if reason == DEVREASON_PREPARE_ERROR or reason == DEVREASON_BLE_DISABLED:
                    for dm in self.devicemanagers_active:
                        info = self.devicemanagers_active_info[dm.get_uid()]
                        self.set_operation_ended(info)
                        if dm not in self.devicemanagers_active_done:
                            self.devicemanagers_active_done.append(dm)
                    del self.devicemanagers_active[:]
                else:
                    Timer(
                        0,
                        partial(self.start_remaining_connection_operations,
                                bytimer=False))
            elif (GenericDeviceManager.is_connected_state_s(oldstate)
                  or oldstate == DEVSTATE_DISCONNECTING
                  ) and newstate == DEVSTATE_DISCONNECTED:
                oper = 'c' if info['operation'] != 'd' else 'd'
                if reason != DEVREASON_REQUESTED:
                    info['operation'] = oper
                    if dm in self.devicemanagers_active_done:
                        self.devicemanagers_active_done.remove(dm)
                    if dm not in self.devicemanagers_active:
                        self.devicemanagers_active.append(dm)
                        GenericDeviceManager.sort(self.devicemanagers_active)
                else:
                    self.set_operation_ended(info)
                    self.main_session = None
                    if dm in self.devicemanagers_active:
                        self.devicemanagers_active.remove(dm)
                        self.devicemanagers_active_done.append(dm)
                Timer(
                    0,
                    partial(self.start_remaining_connection_operations,
                            bytimer=False))

    async def init_db(self, file):
        self.db = await aiosqlite.connect(file)
        if not isinstance(self.db, aiosqlite.Connection):
            self.db = None
        else:
            self.db.row_factory = aiosqlite.Row
            modules = glob.glob(join(dirname(__file__), "..", "db", "*.py*"))
            pls = [splitext(basename(f))[0] for f in modules if isfile(f)]
            import importlib
            import inspect
            for x in pls:
                try:
                    m = importlib.import_module(f"db.{x}")
                    clsmembers = inspect.getmembers(m, inspect.isclass)
                    for cla in clsmembers:
                        query = getattr(cla[1], '__create_table_query__')
                        if query:
                            # _LOGGER.debug(f'Executing query {query}')
                            await self.db.execute(query)
                            cla[1].set_update_columns()
                    await self.db.execute('PRAGMA foreign_keys = ON')
                except Exception:
                    _LOGGER.warning(traceback.format_exc())
            await self.db.commit()

    def on_bluetooth_disabled(self, inst, wasdisabled, ok):
        self.undo_enable_operations()

    def undo_enable_operations(self):
        for nm, act in self.devicemanagers_pre_actions.items():
            if nm in self.undo_info and self.undo_info[nm]:
                del self.undo_info[nm]
                preact = act(self.loop)
                preact.undo(self.on_bluetooth_disabled)
                break
        self.stop_event.set()

    async def uninit_db(self):
        if self.db:
            await self.db.commit()
            await self.db.close()

    async def stop(self):
        self.undo_enable_operations()
        await self.stop_event.wait()
        self.oscer.uninit()
        await self.uninit_db()
        if self.android:
            self.br.stop()
        self.stop_service()

    def stop_service(self):
        if self.android:
            self.reset_service_notifications()
            self.service.stopForeground(True)
            self.service.stopSelf()
class AndroidWiFiManager(WiFiManager):
    def __init__(self, config, logger, api):
        super(AndroidWiFiManager, self).__init__(config, logger, api)
        self.general_android_conn = GeneralAndroidConnectivity(
            self.logger, self.api)
        self.wifi_android_controller = WiFiAndroidController(
            self.logger, self.general_android_conn)

        self.context = PythonService.mService
        self.wifi_manager = self.context.getSystemService(Context.WIFI_SERVICE)
        self.conn_manager = self.context.getSystemService(
            Context.CONNECTIVITY_SERVICE)

        self.conn_change_br = BroadcastReceiver(
            self.handle_conn_change_alert,
            actions=[ConnectivityManager.CONNECTIVITY_ACTION])
        self.addConnectionAlert(
            self.general_android_conn.updateConnectivityMgmtObj)

    def start(self):
        super(AndroidWiFiManager, self).start()
        ip_addr = self.general_android_conn.getLocalIpAddress()
        if ip_addr is not None and ip_addr != "":
            self.general_android_conn.updateConnectivityMgmtObj(
                "{\"status\":\"CONNECTED\", \"ip_address\":\"" + ip_addr +
                "\", \"ssid\":\" \"}")

        #GeneralConnectivity.setOpenMTCIntentAction(self.internalIntentAction)
        #GeneralConnectivity.setOpenMTCAndroidAppPackageName(self.android_app_package)
        #WiFiController.startConnectionAlert()
        results = self.wifi_android_controller.scanWiFiNetworks()
        #results = WiFiAndroidController.scanWiFiNetworks()
        #        results = Hardware.getWiFiNetworks()
        self.logger.info("the result of wifi scan was " + results)

        #        WiFiController.addNetworks(String(str(json.dumps(self.config["networks"],separators=(',', ':')))))
        network_array = json.loads(
            json.dumps(self.config["networks"], separators=(',', ':')))
        for network in network_array:
            self.logger.info("network info is " + str(network))
            network_str = str(json.dumps(network, separators=(',', ':')))
            self.logger.info("network info is " + network_str)
            self.wifi_android_controller.addConfiguredNetwork(network_str)
            #WiFiController.addConfiguredNetwork(String(network_str))

#        default_network = "guest_open"
#        default_network = "guest_wpa_preshared"
        default_network = self.config["default_network"]
        self.logger.info("default_network is " + default_network)
        self.wifi_android_controller.connectToNetwork(default_network)
        #WiFiController.connectToNetwork(default_network)

    def connectToNetwork(self, networkSSID, conn_callback=None):
        self.wifi_android_controller.connectToNetwork(networkSSID,
                                                      conn_callback)

    def addConnectionAlert(self, callback):
        if len(self.conn_change_callback_list) == 0:
            self.conn_change_br.start()
        super(AndroidWiFiManager, self).addConnectionAlert(callback)

    def removeConnectionAlert(self, callback):
        super(AndroidWiFiManager, self).removeConnectionAlert(callback)
        if len(self.conn_change_callback_list) == 0:
            self.conn_change_br.stop()

    def handle_conn_change_alert(self, context, intent):
        action = intent.getAction()
        ssid = ""
        ip_address = ""
        self.logger.info("received intent on " + action)

        if action != ConnectivityManager.CONNECTIVITY_ACTION:
            return

        if intent.hasExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY):
            #intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true)){
            self.logger.info(
                "received information that the device disconnected and no network is available"
            )
            self.conn_change_callback("DISCONNECTED", "", "")
            return

        net_type = intent.getIntExtra("networkType", -1)
        self.logger.info("network type is " + str(net_type))

        if net_type != ConnectivityManager.TYPE_WIFI:
            return

        info = self.conn_manager.getNetworkInfo(net_type)
        state = info.getState()
        self.logger.info("wifi connectivity state is " + str(state.toString()))

        if str(state.toString()) != "CONNECTED":
            return

        self.logger.info(
            "received information about connectivity change for WiFi")

        # send intent to update connectivity status
        self.logger.info(
            "received information that the device connected on WiFi")
        wifiInfo = self.wifi_manager.getConnectionInfo()
        ssid = wifiInfo.getSSID()
        self.logger.info("device is now connected on WiFi on SSID " +
                         str(ssid))

        #        ip_address = self.general_android_conn.getLocalIpAddress()
        ip_address = GeneralConnectivity.getLocalIpAddress()

        if ip_address is None:
            self.logger.info("device is not having any IP assigned")
            self.conn_change_callback("NO IP ADDRESS", "", ssid)
        else:
            self.logger.info("device is now connected with IP " +
                             str(ip_address))
            #TODO: handle any promise that is waiting for the reply
            self.conn_change_callback("CONNECTED", ip_address, ssid)
            self.current_ssid = ssid[1:-1]
            return
Esempio n. 7
0
class Application(MDApp):
    results = set()
    wifi = None
    br = None

    def build(self):

        return Builder.load_string(KV)

    def register_broadcats_receiver(self):
        if not self.br:
            self.br = BroadcastReceiver(
                self.on_broadcast, actions=['SCAN_RESULTS_AVAILABLE_ACTION'])
            self.br.start()

    def on_broadcast(self, context, intent):
        success = intent.getBooleanExtra(
            WifiManager.EXTRA_RESULTS_UPDATED, False)

        if success:
            self.scan_success()
        else:
            self.scan_failure()

    def start_scan(self):

        self.register_broadcats_receiver()
        context = mActivity.getApplicationContext()
        wifiManager = cast(
            WifiManager, context.getSystemService(Context.WIFI_SERVICE))

        self.wifi = wifiManager
        success = self.wifi.startScan()
        if not success:
            self.scan_failure()

    def scan_success(self):
        self.root.ids.lbl.text = ''
        if not self.wifi:
            return

        results = self.wifi.getScanResults()

        for i in range(results.size()):
            result = results.get(i)
            self.results.add(result)
            self.root.ids.lbl.text += f'{result.SSID}\n'

    def on_start(self):
        self.register_broadcats_receiver()
        request_permissions([Permission.ACCESS_FINE_LOCATION])

    def on_resume(self):
        self.register_broadcats_receiver()

    def on_pause(self):
        self.stop_scan()
        return True

    def stop_scan(self):
        if self.br:
            self.br.stop()
            self.br = None
        self.root.ids.lbl.text = ''

    def scan_failure(self):
        if self.results:
            for result in self.results:
                self.root.ids.lbl.text += f'{result}\n'
        else:
            self.root.ids.lbl.text = 'something went wrong'
        self.stop_scan()