示例#1
0
def setup_minimal_master_platform(port):
    # type: (str) -> None
    config = ConfigParser()
    config.read(constants.get_config_file())

    platform = Platform.get_platform()
    Injectable.value(controller_serial=Serial(port, 115200))

    if platform == Platform.Type.DUMMY:
        Injectable.value(maintenance_communicator=None)
        Injectable.value(master_controller=MasterDummyController())
    elif platform in Platform.CoreTypes:
        from master.core import ucan_communicator
        _ = ucan_communicator
        core_cli_serial_port = config.get('OpenMotics', 'cli_serial')
        Injectable.value(cli_serial=Serial(core_cli_serial_port, 115200))
        Injectable.value(master_communicator=CoreCommunicator())
        Injectable.value(maintenance_communicator=None)
        Injectable.value(memory_file=MemoryFile())
        Injectable.value(master_controller=MasterCoreController())
    elif platform in Platform.ClassicTypes:
        Injectable.value(
            eeprom_db=constants.get_eeprom_extension_database_file())
        from master.classic import eeprom_extension
        _ = eeprom_extension
        Injectable.value(master_communicator=MasterCommunicator())
        Injectable.value(maintenance_communicator=None)
        Injectable.value(master_controller=MasterClassicController())
    else:
        logger.warning('Unhandled master implementation for %s', platform)
示例#2
0
 def _register_background_consumers(self):
     if self._master_version and not self._background_consumers_registered:
         if Platform.get_platform() == Platform.Type.CLASSIC:
             # This import/code will eventually be migrated away to MasterControllers
             from master.master_communicator import BackgroundConsumer
             self._master_communicator.register_consumer(
                 BackgroundConsumer(
                     master_api.shutter_status(self._master_version), 0,
                     self._on_shutter_update))
             self._background_consumers_registered = True
示例#3
0
    def get_state(self):
        authorized_mode = self._authorized_mode
        if Platform.get_platform() == Platform.Type.CORE_PLUS:
            authorized_mode = True  # TODO: Should be handled by actual button

        return {
            'run_gpio': self._last_run_gpio,
            'run_i2c': self._last_run_i2c,
            'run_buttons': self._last_button_check,
            'run_state_check': self._last_state_check,
            'authorized_mode': authorized_mode
        }
示例#4
0
def check_gateway_health(timeout=60):
    since = time.time()
    pending = ['unknown']
    while since > time.time() - timeout:
        try:
            http_port = Platform.http_port()
            response = requests.get('http://127.0.0.1:{}/health_check'.format(http_port), timeout=2)
            data = response.json()
            if data['success']:
                pending = [k for k, v in data['health'].items() if not v['state']]
                if not pending:
                    return
        except Exception as ex:
            pass
        time.sleep(10)
    message = 'health check failed {}'.format(pending)
    logger.error(message)
    raise SystemExit(EXIT_CODES['failed_health_check'])
示例#5
0
 def __init__(
         self,
         master_communicator=INJECTED):  # type: (CoreCommunicator) -> None
     super(FrontpanelCoreController, self).__init__()
     self._master_communicator = master_communicator
     self._master_communicator.register_consumer(
         BackgroundConsumer(CoreAPI.event_information(), 0,
                            self._handle_event))
     self._led_states = {}  # type: Dict[str, LedStateTracker]
     self._led_event_lock = Lock()
     self._carrier = True
     self._connectivity = True
     self._activity = False
     self._cloud = False
     self._vpn = False
     self._led_drive_states = {}  # type: Dict[str, Tuple[bool, str]]
     self._check_buttons_thread = None
     self._authorized_mode_buttons = [False, False]
     self._authorized_mode_buttons_pressed_since = None  # type: Optional[float]
     self._authorized_mode_buttons_released = False
     self._platform = Platform.get_platform()
示例#6
0
if __name__ == '__main__':
    setup_logger()

    config = ConfigParser()
    config.read(constants.get_config_file())

    Injectable.value(config_db_lock=Lock())
    Injectable.value(config_db=constants.get_config_database_file())
    Injectable.value(eeprom_db=constants.get_eeprom_extension_database_file())

    controller_serial_port = config.get('OpenMotics', 'controller_serial')
    Injectable.value(controller_serial=Serial(controller_serial_port, 115200))

    from gateway import config as config_controller
    _ = config_controller
    if Platform.get_platform() == Platform.Type.CORE_PLUS:
        from gateway.hal import master_controller_core  # type: ignore
        from master_core import maintenance, core_communicator, ucan_communicator  # type: ignore
        _ = master_controller_core, maintenance, core_communicator, ucan_communicator  # type: ignore
    else:
        from gateway.hal import master_controller_classic  # type: ignore
        from master import maintenance, master_communicator, eeprom_extension  # type: ignore
        _ = master_controller_classic, maintenance, master_communicator, eeprom_extension  # type: ignore

    lock_file = constants.get_init_lockfile()
    if os.path.isfile(lock_file):
        with open(lock_file) as fd:
            content = fd.read()

        if content == 'factory_reset':
            logger.info('Running factory reset...')
示例#7
0
"""

import sqlite3
import logging
import time
import pytz
from datetime import datetime
from croniter import croniter
from random import randint
from threading import Thread
from ioc import Injectable, Inject, INJECTED, Singleton
from platform_utils import Platform
from gateway.webservice import params_parser
import ujson as json

if Platform.get_platform() == Platform.Type.CLASSIC:
    from master.master_communicator import CommunicationTimedOutException
else:
    # TODO: Replace for the Core+
    class CommunicationTimedOutException(Exception):  # type: ignore
        pass


logger = logging.getLogger('openmotics')


class Schedule(object):

    timezone = None

    def __init__(self, id, name, start, repeat, duration, end, schedule_type,
示例#8
0
def update(version, expected_md5):
    """
    Execute the actual update: extract the archive and execute the bash update script.

    :param version: the new version (after the update).
    :param expected_md5: the md5 sum provided by the server.
    """
    version_mapping = {}
    has_master_hardware = Platform.has_master_hardware()

    try:
        config = ConfigParser()
        config.read(constants.get_config_file())
        from_version = config.get('OpenMotics', 'version')
        logger.info('==================================')
        logger.info('Starting update {} -> {}'.format(from_version, version))

        update_file = constants.get_update_file()
        update_dir = os.path.dirname(update_file)
        # Change to update directory.
        os.chdir(update_dir)

        if os.path.exists(update_file):
            logger.info(' -> Extracting update.tgz')
            extract_legacy_update(update_file, expected_md5)
        else:
            logger.info(' -> Fetching metadata')
            meta = fetch_metadata(config, version, expected_md5)
            logger.info(' -> Downloading firmware for update {}'.format(meta['version']))
            for data in meta['firmwares']:
                download_firmware(data['type'], data['url'], data['sha256'])
                version_mapping[data['type']] = data['version']
    except Exception:
        logger.exception('failed to preprepare update')
        raise SystemExit(EXIT_CODES['failed_preprepare_update'])

    errors = []
    services_running = True
    try:
        date = datetime.now().strftime('%Y%m%d%H%M%S')

        # TODO: should update and re-execute itself before proceeding?

        logger.info(' -> Checking services')
        check_services()

        logger.info(' -> Stopping services')
        stop_services()
        services_running = False

        if has_master_hardware:
            gateway_os = FIRMWARE_FILES['gateway_os']
            if os.path.exists(gateway_os):
                os_version = version_mapping.get('gateway_os')
                logger.info(' -> Updating Gateway OS to {0}'.format(os_version if os_version else 'unknown version'))
                error = update_gateway_os(gateway_os, os_version)
                if error:
                    errors.append(error)

        gateway_service = FIRMWARE_FILES['gateway_service']
        if os.path.exists(gateway_service):
            service_version = version_mapping.get('gateway_service')
            logger.info(' -> Updating Gateway service to {0}'.format(service_version if service_version else 'unknown version'))
            error = update_gateway_backend(gateway_service, date, service_version)
            if error:
                errors.append(error)

        if has_master_hardware:
            master_type = get_master_type()
            master_firmware = FIRMWARE_FILES[master_type]
            if os.path.exists(master_firmware):
                master_version = version_mapping.get(master_type)
                logger.info(' -> Updating Master firmware to {0}'.format(master_version if master_version else 'unknown version'))
                error = update_master_firmware(master_type, master_firmware, master_version)
                if error:
                    errors.append(error)

            for module, filename, arguments in [('energy', FIRMWARE_FILES['energy'], []),
                                                ('power', FIRMWARE_FILES['power'], ['--8'])]:
                if os.path.exists(filename):
                    energy_version = version_mapping.get(module)
                    logger.info(' -> Updating {0} firmware to {1}'.format(module, energy_version if energy_version else 'unknown version'))
                    error = update_energy_firmware(module, filename, energy_version, arguments)
                    if error:
                        errors.append(error)

            for module in MODULE_TYPES:
                module_firmware = FIRMWARE_FILES[module]
                module_version = version_mapping.get(module)
                if os.path.exists(module_firmware):
                    logger.info(' -> Updating {0} firmware to {1}'.format(module, module_version if module_version else 'unknown version'))
                    error = update_module_firmware(module, module_firmware, module_version)
                    if error:
                        errors.append(error)

            logger.info('Checking master communication')
            check_master_communication()

        gateway_frontend = FIRMWARE_FILES['gateway_frontend']
        if os.path.exists(gateway_frontend):
            frontend_version = version_mapping.get('gateway_frontend')
            logger.info(' -> Updating Gateway frontend to {0}'.format(frontend_version if frontend_version else 'unknown version'))
            error = update_gateway_frontend(gateway_frontend, date, frontend_version)
            if error:
                errors.append(error)

        if os.path.exists(gateway_frontend) or os.path.exists(gateway_service):
            clean_update_backups()

        logger.info(' -> Starting services')
        start_services()
        services_running = True

        logger.info(' -> Waiting for health check')
        check_gateway_health()

    except Exception as exc:
        logger.exception('Unexpected exception updating')
        errors.append(exc)
        # TODO: rollback
    finally:
        if not services_running:
            logger.info(' -> Starting services')
            start_services()

        logger.info(' -> Running cleanup')
        cmd('rm -v -rf {}/*'.format(update_dir), shell=True)

        if errors:
            logger.error('Exceptions:')
            for error in errors:
                logger.error('- {0}'.format(error))
            raise errors[0]

        config.set('OpenMotics', 'version', version)
        temp_file = constants.get_config_file() + '.update'
        with open(temp_file, 'w') as configfile:
            config.write(configfile)
        shutil.move(temp_file, constants.get_config_file())
        cmd(['sync'])

        if os.path.exists('/tmp/post_update_reboot'):
            logger.info('Scheduling reboot in 5 minutes')
            subprocess.Popen('sleep 300 && reboot', close_fds=True, shell=True)

        logger.info('DONE')
        logger.info('exit 0')
示例#9
0
def get_master_type():
    if Platform.get_platform() in Platform.CoreTypes:
        return 'master_coreplus'
    else:
        return 'master_classic'
示例#10
0
def main():
    # type: () -> None
    """ The main function. """
    parser = argparse.ArgumentParser(description='Tool to control the master.')
    parser.add_argument('--port', dest='port', action='store_true',
                        help='get the serial port device')
    parser.add_argument('--sync', dest='sync', action='store_true',
                        help='sync the serial port')
    parser.add_argument('--reset', dest='reset', action='store_true',
                        help='reset the master')
    parser.add_argument('--hard-reset', dest='hardreset', action='store_true',
                        help='perform a hardware reset on the master')
    parser.add_argument('--version', dest='version', action='store_true',
                        help='get the version of the master')
    parser.add_argument('--wipe', dest='wipe', action='store_true',
                        help='wip the master eeprom')
    parser.add_argument('--update', dest='update', action='store_true',
                        help='update the master firmware')
    parser.add_argument('--master-firmware-classic',
                        help='path to the hexfile with the classic firmware')
    parser.add_argument('--master-firmware-core',
                        help='path to the hexfile with the core+ firmware')

    args = parser.parse_args()

    setup_logger()

    config = ConfigParser()
    config.read(constants.get_config_file())

    port = config.get('OpenMotics', 'controller_serial')
    if args.port:
        print(port)
        return

    if not any([args.sync, args.version, args.reset, args.hardreset, args.wipe, args.update]):
        parser.print_help()

    setup_minimal_master_platform(port)
    platform = Platform.get_platform()

    if args.hardreset:
        master_cold_reset()
        return
    elif args.update:
        if platform in Platform.CoreTypes:
            firmware = args.master_firmware_core
            if not firmware:
                print('error: --master-firmware-core is required to update')
                sys.exit(1)
        else:
            firmware = args.master_firmware_classic
            if not firmware:
                print('error: --master-firmware-classic is required to update')
                sys.exit(1)
        master_update(firmware)
        return

    communicator = get_communicator()
    communicator.start()
    try:
        if args.sync:
            master_sync()
        elif args.version:
            master_version()
        elif args.reset:
            master_reset()
        elif args.wipe:
            master_factory_reset()
    finally:
        communicator.stop()
示例#11
0
def main():
    supported_modules = ['O', 'R', 'D', 'I', 'T', 'C']
    supported_modules_gen3 = ['O3', 'R3', 'D3', 'I3', 'T3', 'C3']
    supported_can_modules = ['UC']
    all_supported_modules = supported_modules + supported_modules_gen3 + supported_can_modules

    parser = argparse.ArgumentParser(
        description='Tool to bootload the slave modules.')

    parser.add_argument(
        '-t',
        '--type',
        dest='type',
        choices=all_supported_modules +
        [m.lower() for m in all_supported_modules],
        required=True,
        help='The type of module to bootload (choices: {0})'.format(
            ', '.join(all_supported_modules)))
    parser.add_argument('-f',
                        '--file',
                        dest='file',
                        required=True,
                        help='The filename of the hex file to bootload')
    parser.add_argument('-v',
                        '--version',
                        dest='version',
                        required=False,
                        help='The version of the firmware to flash')
    parser.add_argument('--verbose',
                        dest='verbose',
                        action='store_true',
                        help='Show the serial output')

    args = parser.parse_args()
    module_type = args.type.upper()
    filename = args.file
    version = args.version
    gen3_firmware = module_type.endswith('3')
    if gen3_firmware:
        module_type = module_type[0]

    config = ConfigParser()
    config.read(constants.get_config_file())
    port = config.get('OpenMotics', 'controller_serial')

    setup_minimal_master_platform(port)

    communicator = get_communicator()
    communicator.start()
    try:
        if Platform.get_platform() in Platform.CoreTypes:
            from master.core.slave_updater import SlaveUpdater

            update_success = SlaveUpdater.update_all(
                module_type=module_type,
                hex_filename=filename,
                gen3_firmware=gen3_firmware,
                version=version)
        else:
            from master.classic.slave_updater import bootload_modules

            try:
                if os.path.getsize(args.file) <= 0:
                    print('Could not read hex or file is empty: {0}'.format(
                        args.file))
                    return False
            except OSError as ex:
                print('Could not open hex: {0}'.format(ex))
                return False

            if module_type == 'UC':
                print(
                    'Updating uCAN modules not supported on Classic platform')
                return True  # Don't fail the update

            update_success = bootload_modules(module_type=module_type,
                                              filename=filename,
                                              gen3_firmware=gen3_firmware,
                                              version=version)
    finally:
        communicator.stop()
        time.sleep(3)

    return update_success
示例#12
0
def setup_platform(message_client_name):
    # type: (Optional[str]) -> None
    setup_target_platform(Platform.get_platform(), message_client_name)
示例#13
0
 def start(self):
     """ Starts the monitoring thread """
     self._ensure_gateway_api()
     if Platform.get_platform() == Platform.Type.CLASSIC:
         self._thread.start()
示例#14
0
    def build_graph():
        config = ConfigParser()
        config.read(constants.get_config_file())

        config_lock = Lock()
        scheduling_lock = Lock()
        metrics_lock = Lock()

        config_database_file = constants.get_config_database_file()

        # TODO: Clean up dependencies more to reduce complexity

        # IOC announcements
        # When below modules are imported, the classes are registerd in the IOC graph. This is required for
        # instances that are used in @Inject decorated functions below, and is also needed to specify
        # abstract implementations depending on e.g. the platform (classic vs core) or certain settings (classic
        # thermostats vs gateway thermostats)
        from power import power_communicator, power_controller
        from plugins import base
        from gateway import (metrics_controller, webservice, scheduling,
                             observer, gateway_api, metrics_collector,
                             maintenance_controller, comm_led_controller,
                             users, pulses, config as config_controller,
                             metrics_caching, watchdog)
        from cloud import events
        _ = (metrics_controller, webservice, scheduling, observer, gateway_api,
             metrics_collector, maintenance_controller, base, events,
             power_communicator, comm_led_controller, users, power_controller,
             pulses, config_controller, metrics_caching, watchdog)
        if Platform.get_platform() == Platform.Type.CORE_PLUS:
            from gateway.hal import master_controller_core
            from master_core import maintenance, core_communicator, ucan_communicator
            from master import eeprom_extension  # TODO: Obsolete, need to be removed
            _ = master_controller_core, maintenance, core_communicator, ucan_communicator
        else:
            from gateway.hal import master_controller_classic
            from master import maintenance, master_communicator, eeprom_extension
            _ = master_controller_classic, maintenance, master_communicator, eeprom_extension

        thermostats_gateway_feature = Feature.get_or_none(
            name='thermostats_gateway')
        thermostats_gateway_enabled = thermostats_gateway_feature is not None and thermostats_gateway_feature.enabled
        if Platform.get_platform(
        ) == Platform.Type.CORE_PLUS or thermostats_gateway_enabled:
            from gateway.thermostat.gateway import thermostat_controller_gateway
            _ = thermostat_controller_gateway
        else:
            from gateway.thermostat.master import thermostat_controller_master
            _ = thermostat_controller_master

        # IPC
        Injectable.value(message_client=MessageClient('openmotics_service'))

        # Cloud API
        parsed_url = urlparse(config.get('OpenMotics', 'vpn_check_url'))
        Injectable.value(gateway_uuid=config.get('OpenMotics', 'uuid'))
        Injectable.value(cloud_endpoint=parsed_url.hostname)
        Injectable.value(cloud_port=parsed_url.port)
        Injectable.value(cloud_ssl=parsed_url.scheme == 'https')
        Injectable.value(cloud_api_version=0)

        # User Controller
        Injectable.value(user_db=config_database_file)
        Injectable.value(user_db_lock=config_lock)
        Injectable.value(token_timeout=3600)
        Injectable.value(
            config={
                'username': config.get('OpenMotics', 'cloud_user'),
                'password': config.get('OpenMotics', 'cloud_pass')
            })

        # Configuration Controller
        Injectable.value(config_db=config_database_file)
        Injectable.value(config_db_lock=config_lock)

        # Energy Controller
        power_serial_port = config.get('OpenMotics', 'power_serial')
        Injectable.value(power_db=constants.get_power_database_file())
        if power_serial_port:
            Injectable.value(power_serial=RS485(
                Serial(power_serial_port, 115200, timeout=None)))
        else:
            Injectable.value(power_serial=None)
            Injectable.value(power_communicator=None)
            Injectable.value(power_controller=None)

        # Pulse Controller
        Injectable.value(pulse_db=constants.get_pulse_counter_database_file())

        # Scheduling Controller
        Injectable.value(
            scheduling_db=constants.get_scheduling_database_file())
        Injectable.value(scheduling_db_lock=scheduling_lock)

        # Master Controller
        controller_serial_port = config.get('OpenMotics', 'controller_serial')
        Injectable.value(
            controller_serial=Serial(controller_serial_port, 115200))
        if Platform.get_platform() == Platform.Type.CORE_PLUS:
            from master_core.memory_file import MemoryFile, MemoryTypes
            core_cli_serial_port = config.get('OpenMotics', 'cli_serial')
            Injectable.value(cli_serial=Serial(core_cli_serial_port, 115200))
            Injectable.value(passthrough_service=None)  # Mark as "not needed"
            Injectable.value(
                memory_files={
                    MemoryTypes.EEPROM: MemoryFile(MemoryTypes.EEPROM),
                    MemoryTypes.FRAM: MemoryFile(MemoryTypes.FRAM)
                })
            # TODO: Remove; should not be needed for Core
            Injectable.value(
                eeprom_db=constants.get_eeprom_extension_database_file())
        else:
            passthrough_serial_port = config.get('OpenMotics',
                                                 'passthrough_serial')
            Injectable.value(
                eeprom_db=constants.get_eeprom_extension_database_file())
            if passthrough_serial_port:
                Injectable.value(
                    passthrough_serial=Serial(passthrough_serial_port, 115200))
                from master.passthrough import PassthroughService
                _ = PassthroughService  # IOC announcement
            else:
                Injectable.value(passthrough_service=None)

        # Metrics Controller
        Injectable.value(metrics_db=constants.get_metrics_database_file())
        Injectable.value(metrics_db_lock=metrics_lock)

        # Webserver / Presentation layer
        Injectable.value(ssl_private_key=constants.get_ssl_private_key_file())
        Injectable.value(ssl_certificate=constants.get_ssl_certificate_file())
示例#15
0
文件: rooms.py 项目: rolaya/gateway
    def _migrate(cls,
                 master_controller=INJECTED
                 ):  # type: (MasterClassicController) -> None
        # Core(+) platforms never had non-ORM rooms
        if Platform.get_platform() in Platform.CoreTypes:
            return

        # Import legacy code
        @Inject
        def _load_eeprom_extension(eeprom_extension=INJECTED):
            # type: (EepromExtension) -> EepromExtension
            return eeprom_extension

        eext_controller = _load_eeprom_extension()
        from master.classic.eeprom_models import (OutputConfiguration,
                                                  InputConfiguration,
                                                  SensorConfiguration,
                                                  ShutterConfiguration,
                                                  ShutterGroupConfiguration,
                                                  PulseCounterConfiguration)

        rooms = {}  # type: Dict[int, Room]
        floors = {}  # type: Dict[int, Floor]

        # Rooms and floors
        logger.info('* Rooms & floors')
        for room_id in range(100):
            try:
                RoomsMigrator._get_or_create_room(eext_controller,
                                                  room_id,
                                                  rooms,
                                                  floors,
                                                  skip_empty=True)
            except Exception:
                logger.exception('Could not migrate single RoomConfiguration')

        # Main objects
        for eeprom_model, orm_model, filter_ in [
            (OutputConfiguration, Output, lambda o: True),
            (InputConfiguration, Input, lambda i: i.module_type in ['i', 'I']),
            (SensorConfiguration, Sensor, lambda s: True),
            (ShutterConfiguration, Shutter, lambda s: True),
            (ShutterGroupConfiguration, ShutterGroup, lambda s: True)
        ]:
            logger.info('* {0}s'.format(eeprom_model.__name__))
            try:
                for classic_orm in master_controller._eeprom_controller.read_all(
                        eeprom_model):
                    try:
                        object_id = classic_orm.id
                        if object_id is None:
                            continue
                        if not filter_(classic_orm):
                            RoomsMigrator._delete_eext_fields(
                                eext_controller, eeprom_model.__name__,
                                object_id, ['room'])
                            continue
                        try:
                            room_id = int(
                                RoomsMigrator._read_eext_fields(
                                    eext_controller, eeprom_model.__name__,
                                    object_id, ['room']).get('room', 255))
                        except ValueError:
                            room_id = 255
                        object_orm, _ = orm_model.get_or_create(
                            number=object_id)  # type: ignore
                        if room_id == 255:
                            object_orm.room = None
                        else:
                            object_orm.room = RoomsMigrator._get_or_create_room(
                                eext_controller, room_id, rooms, floors)
                        object_orm.save()
                        RoomsMigrator._delete_eext_fields(
                            eext_controller, eeprom_model.__name__, object_id,
                            ['room'])
                    except Exception:
                        logger.exception('Could not migrate single {0}'.format(
                            eeprom_model.__name__))
            except Exception:
                logger.exception('Could not migrate {0}s'.format(
                    eeprom_model.__name__))

        # PulseCounters
        pulse_counter = None  # type: Optional[PulseCounter]
        # - Master
        try:
            logger.info('* PulseCounters (master)')
            for pulse_counter_classic_orm in master_controller._eeprom_controller.read_all(
                    PulseCounterConfiguration):
                try:
                    pulse_counter_id = pulse_counter_classic_orm.id
                    try:
                        room_id = int(
                            RoomsMigrator._read_eext_fields(
                                eext_controller, 'PulseCounterConfiguration',
                                pulse_counter_id, ['room']).get('room', 255))
                    except ValueError:
                        room_id = 255
                    pulse_counter = PulseCounter.get_or_none(
                        number=pulse_counter_id)
                    if pulse_counter is None:
                        pulse_counter = PulseCounter(
                            number=pulse_counter_id,
                            name=pulse_counter_classic_orm.name,
                            persistent=False,
                            source=u'master')
                    else:
                        pulse_counter.name = pulse_counter_classic_orm.name
                        pulse_counter.persistent = False
                        pulse_counter.source = u'master'
                    if room_id == 255:
                        pulse_counter.room = None
                    else:
                        pulse_counter.room = RoomsMigrator._get_or_create_room(
                            eext_controller, room_id, rooms, floors)
                    pulse_counter.save()
                    RoomsMigrator._delete_eext_fields(
                        eext_controller, 'PulseCounterConfiguration',
                        pulse_counter_id, ['room'])
                except Exception:
                    logger.exception(
                        'Could not migrate classic master PulseCounter')
        except Exception:
            logger.exception('Could not migrate classic master PulseCounters')
        # - Old SQLite3
        old_sqlite_db = constants.get_pulse_counter_database_file()
        if os.path.exists(old_sqlite_db):
            try:
                logger.info('* PulseCounters (gateway)')
                import sqlite3
                connection = sqlite3.connect(
                    old_sqlite_db,
                    detect_types=sqlite3.PARSE_DECLTYPES,
                    check_same_thread=False,
                    isolation_level=None)
                cursor = connection.cursor()
                for row in cursor.execute(
                        'SELECT id, name, room, persistent FROM pulse_counters ORDER BY id ASC;'
                ):
                    try:
                        pulse_counter_id = int(row[0])
                        room_id = int(row[2])
                        pulse_counter = PulseCounter.get_or_none(
                            number=pulse_counter_id)
                        if pulse_counter is None:
                            pulse_counter = PulseCounter(
                                number=pulse_counter_id,
                                name=str(row[1]),
                                persistent=row[3] >= 1,
                                source=u'gateway')
                        else:
                            pulse_counter.name = str(row[1])
                            pulse_counter.persistent = row[3] >= 1
                            pulse_counter.source = u'gateway'
                        if room_id == 255:
                            pulse_counter.room = None
                        else:
                            pulse_counter.room = RoomsMigrator._get_or_create_room(
                                eext_controller, room_id, rooms, floors)
                        pulse_counter.save()
                    except Exception:
                        logger.exception(
                            'Could not migratie gateway PulseCounter')
                os.rename(old_sqlite_db, '{0}.bak'.format(old_sqlite_db))
            except Exception:
                logger.exception('Could not migrate gateway PulseCounters')