示例#1
0
    def blocking_login(self):
        def token_updater(token):
            asyncio.run_coroutine_threadsafe(self.token_updated(token),
                                             self.loop).result()

        if self._token != "":
            self._auth = Auth(self._ridentifier + "/1.0", self._token,
                              token_updater)
        else:
            if self._password != "":
                self._auth = Auth(self._ridentifier + "/1.0", None,
                                  token_updater)
                if self._2facode:
                    self._auth.fetch_token(self._username, self._password,
                                           self._2facode)
                else:
                    try:
                        self._auth.fetch_token(self._username, self._password)
                    except AccessDeniedError:
                        return "AccessDenied: wrong username or password"
                    except MissingTokenError:
                        return "please set 2fa_code"
            else:
                return "please set password"
        self._ring = Ring(self._auth)
示例#2
0
def ring(mock_ring_requests):
    """Return ring object."""
    auth = Auth("PythonRingDoorbell/0.6")
    auth.fetch_token("foo", "bar")
    ring = Ring(auth)
    ring.update_data()
    return ring
示例#3
0
def initialize_ring():
    cache_file = Path("token.cache")

    def token_updated(token):
        cache_file.write_text(json.dumps(token))

    def otp_callback():
        auth_code = input("2FA code: ")
        return auth_code

    if cache_file.is_file():
        auth = Auth("CamBot/1.0", json.loads(cache_file.read_text()),
                    token_updated)
    else:
        username = input("Username: "******"Password: "******"CamBot/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()
    return ring
示例#4
0
def main():
    if cache_file.is_file():
        auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()), token_updated)
    else:
        username = input("Username: "******"Password: "******"MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()

    devices = ring.devices()
    print(devices)

    doorbells = devices["doorbots"]
    chimes = devices["chimes"]
    stickup_cams = devices["stickup_cams"]

    print(doorbells)
    print(chimes)
    print(stickup_cams)
示例#5
0
def ringOperations(emailname):
    s3 = boto3.client('s3')
    getCacheFileFromBucket(BUCKET_NAME, emailname)

    if cache_file.is_file():
        cachefile = open(CACHE_FILE_NAME, "r")
        tokendata = json.loads(cachefile.read())
        cachefile.close()
        auth = Auth("MyProject/1.0", tokendata, token_updated)
        uploadCacheFileToBucket(BUCKET_NAME, CACHE_FILE_NAME, emailname)

    ring = Ring(auth)
    ring.update_data()

    devices = ring.devices()

    getLatestMotionVideo(devices)
    getFrameFromVideo()
    sourceKey = "video_frame.png"
    imagelabels = getlabels(BUCKET_NAME, sourceKey)
    imagefaces = getfaces(BUCKET_NAME, sourceKey)
    imagetext = gettext(BUCKET_NAME, sourceKey)
    addImageInfotoTable(imagelabels, imagetext, imagefaces)

    s3.delete_object(Bucket=BUCKET_NAME, Key=sourceKey)
    s3.delete_object(Bucket=BUCKET_NAME, Key="last_trigger.mp4")
def main(argv):
    username = ''
    passwd = ''
    token_updated = None
    opts, args = getopt.getopt(argv, "u:p:")
    for opt, arg in opts:
        if opt in ("-u"):
            username = arg
        elif opt in ("-p"):
            passwd = arg
    auth = Auth(None, token_updated)
    auth.fetch_token(username, passwd)
    myring = Ring(auth)
    for dev in list(myring.doorbells):
        dev.update()
        print(dev.id + '||' + dev.family + '||' + dev.name)
示例#7
0
def main(argv):
   username = ''
   passwd = ''
   token_updated = None
   opts, args = getopt.getopt(argv,"u:p:")
   for opt, arg in opts:
      if opt in ("-u"):
         username = arg
      elif opt in ("-p"):
         passwd = arg

   auth = Auth(None, token_updated)
   auth.fetch_token(username, passwd)
   myring = Ring(auth)
   for doorbell in list(myring.doorbells):
        doorbell.update()
        for event in doorbell.history(limit=20):
           print(str(doorbell.id)+'||'+str(event['id'])+'||'+str(event['kind'])+'||'+str(event['answered'])+'||'+str(event['created_at']))
示例#8
0
 def __init__(self):
     if cache_file.is_file():
         auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()),
                     token_updated)
     else:
         username = input("Username: "******"Password: "******"MyProject/1.0", None, token_updated)
         try:
             auth.fetch_token(username, password)
         except MissingTokenError:
             auth.fetch_token(username, password, otp_callback())
     self.ring = Ring(auth)
     self.ring.update_data()
def login():
    username = input("Username: "******"Password: "******"SmartThingsApi/0.1", token_updater=token_updated)
    try:
      auth.fetch_token(username, password)
    except MissingTokenError:
      auth.fetch_token(username, password, otp_callback())
示例#10
0
def initialize_ring():
    if cache_file.is_file():
        auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()),
                    token_updated)
    else:
        auth = Auth("MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(config.ringuser, config.ringpassword)
        except MissingTokenError:
            auth.fetch_token(config.ringuser, config.ringpassword,
                             otp_callback())

    ring = Ring(auth)
    ring.update_data()
    return ring
示例#11
0
def main(download_only=False):
    if cache_file.is_file():
        auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()), token_updated)
    else:
        username = os.environ.get('USERNAME')
        password = os.environ.get('PASSWORD')
        auth = Auth("MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()

    wait_for_update(ring, download_only=download_only)
示例#12
0
async def validate_input(hass: core.HomeAssistant, data):
    """Validate the user input allows us to connect."""

    auth = Auth(f"HomeAssistant/{const.__version__}")

    try:
        token = await hass.async_add_executor_job(
            auth.fetch_token, data["username"], data["password"], data.get("2fa"),
        )
    except MissingTokenError:
        raise Require2FA
    except AccessDeniedError:
        raise InvalidAuth

    return token
示例#13
0
def main():
    if cache_file.is_file():
        auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()),
                    token_updated)
    else:
        username = input("Username: "******"Password: "******"MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()

    devices = ring.devices()
    print(devices)

    doorbells = devices["doorbots"]
    chimes = devices["chimes"]
    stickup_cams = devices["stickup_cams"]

    print(doorbells)
    #print(chimes)
    #print(stickup_cams)
    x = 0
    y = 0
    limit = 100
    doorbell = devices['doorbots'][0]
    typelist = {
        "motion",
        "ding",
    }
    for rt in typelist:
        print(rt)
        for i in doorbell.history(limit=limit, kind=rt):
            print(i['id'])
            doorbell.recording_download(
                doorbell.history(limit=limit, kind=rt)[x]['id'],
                filename=str(i['created_at'].strftime("%m-%d-%Y-%H-%M-%S")) +
                '.mp4',
                override=True)
            x += 1
示例#14
0
def writeAuthFile():

    logging.warn(f"will create new oauth json file at {config('OAUTH_FILE')}")

    username = input("Please enter your ring Username: "******"Please enter your ring Password: "******"MyProject/1.0", None, token_updated)
    try:
        auth.fetch_token(username, password)
    except MissingTokenError:
        auth.fetch_token(username, password, otp_callback())
示例#15
0
def main():
    if cache_file.is_file():
        print("Token has already been set up, loading...")
        auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()),
                    token_updated)
    else:
        username = my_email
        print(
            "This is the first time setting up, getting the token set up now..."
        )
        password = getpass.getpass("Password: "******"MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()
示例#16
0
async def validate_input(opp: core.OpenPeerPower, data):
    """Validate the user input allows us to connect."""

    auth = Auth(f"OpenPeerPower/{const.__version__}")

    try:
        token = await opp.async_add_executor_job(
            auth.fetch_token,
            data["username"],
            data["password"],
            data.get("2fa"),
        )
    except MissingTokenError as err:
        raise Require2FA from err
    except AccessDeniedError as err:
        raise InvalidAuth from err

    return token
def main():
    global cache_file, token_updated, ring
    if not cache_file.is_file():
        print("Token not found", file=sys.stderr)
        exit(1)

    print("Instantiating ring api...")
    auth = Auth(user_agent="SmartThingsApi/0.1",
                token=json.loads(cache_file.read_text()),
                token_updater=token_updated)
    ring = Ring(auth)
    ring.update_data()
    print("Instantiating background job...")
    scheduler = BackgroundScheduler()
    scheduler.add_job(pingring, 'interval', hours=2)
    scheduler.start()
    print("Starting web server...")
    run()
示例#18
0
def main():
    # initialize logger for debugging
    initialize_logger()

    if cache_file.is_file():
        auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()),
                    token_updated)
    else:
        # initialize ring account username and password
        username = config('user')
        password = config('pw')

        # use the Authenticator of the ring_doorbell API
        # tries to fetch token for authentication
        # requests user input for the code if necessary
        auth = Auth("MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    threshold = input(
        "Enter the percentage where-in you want to get reminders: ")
    # loop for checking battery life
    while True:
        ring = Ring(auth)
        ring.update_data()

        # filter the Ring Devices
        devices = ring.devices()
        front_door = devices['authorized_doorbots']

        battery_life = front_door[0].battery_life
        logging.info(f'The current battery life is {battery_life}')
        # if battery is less than threshold, send the e-mail
        if (battery_life <= int(threshold)):
            logging.info("Sending the email")
            send_email(battery_life)

        # loop sleeps for 6 hours 21600
        sleep(3600)
示例#19
0
def main():
    if cache_file.is_file():
        auth = Auth(
            "HomeAssistant/0.105.0dev0",
            json.loads(cache_file.read_text()),
            token_updated,
        )
    else:
        username = input("Username: "******"Password: "******"Hello {ring.session['profile']['first_name']}")
    print()
    pprint(ring.devices_data)
示例#20
0
def main():
    if cache_file.is_file():
        auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()),
                    token_updated)
    else:
        username = input("Username: "******"Password: "******"MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()

    devices = ring.devices()
    pprint(devices)

    # play with the API to figure out which camera you want
    deck = devices['doorbots'][0]
    download(deck)
    print('\nDONE.')
示例#21
0
def main():
    if cache_file.is_file():
        token = json.loads(cache_file.read_text())
        auth = Auth("Ringer/1.0", token, token_updated)
        print(f"Token expires at {expires_at_to_datetime(token['expires_at'])}")
    else:
        username = input("Username: "******"Password: "******"Ringer/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()

    devices = ring.devices()
    pprint(devices)

    doorbell = devices['doorbots'][0]
    history = doorbell.history(limit=100, kind='motion')
    id = history[0]['id']
    doorbell.recording_download(
        id,
        filename=f'doorbell_motion_{id}.mp4',
        override=True)

    cams = devices['stickup_cams']
    for cam in cams:
        history = cam.history(limit=100, kind='motion')
        id = history[0]['id']
        cam.recording_download(
            id,
            filename=f'cam_motion_{id}.mp4',
            override=True)
示例#22
0
# Connect to Hue Bridge
b = Bridge(data['HUE_IP'])

# First time need to press the button on the Bridge and connect (within 30 seconds)
# b.connect()

lights = []
hue_lights = b.lights

print("[Hue] Connected")

# Sign in to Ring
RING_USERNAME = data['RING_USER']
RING_PASSWORD = data['RING_PASS']
auth = Auth("huebell/v1")
auth.fetch_token(RING_USERNAME, RING_PASSWORD)
ring = Ring(auth)
ring.update_data()
print("[Ring] Connected")

# Load doorbell
devices = ring.devices()
doorbell = devices['doorbots'][0]


def flash_lights():
    # Get current status of all lights
    for l in hue_lights:
        light = {
            'name': l.name,
示例#23
0
async def async_setup_entry(hass, entry):
    """Set up a config entry."""
    def token_updater(token):
        """Handle from sync context when token is updated."""
        run_callback_threadsafe(
            hass.loop,
            partial(
                hass.config_entries.async_update_entry,
                entry,
                data={
                    **entry.data, "token": token
                },
            ),
        ).result()

    auth = Auth(f"HomeAssistant/{__version__}", entry.data["token"],
                token_updater)
    ring = Ring(auth)

    try:
        await hass.async_add_executor_job(ring.update_data)
    except AccessDeniedError:
        _LOGGER.error(
            "Access token is no longer valid. Please set up Ring again")
        return False

    hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
        "api":
        ring,
        "devices":
        ring.devices(),
        "device_data":
        GlobalDataUpdater(hass, "device", entry.entry_id, ring,
                          "update_devices", timedelta(minutes=1)),
        "dings_data":
        GlobalDataUpdater(
            hass,
            "active dings",
            entry.entry_id,
            ring,
            "update_dings",
            timedelta(seconds=5),
        ),
        "history_data":
        DeviceDataUpdater(
            hass,
            "history",
            entry.entry_id,
            ring,
            lambda device: device.history(limit=10),
            timedelta(minutes=1),
        ),
        "health_data":
        DeviceDataUpdater(
            hass,
            "health",
            entry.entry_id,
            ring,
            lambda device: device.update_health_data(),
            timedelta(minutes=1),
        ),
    }

    hass.config_entries.async_setup_platforms(entry, PLATFORMS)

    if hass.services.has_service(DOMAIN, "update"):
        return True

    async def async_refresh_all(_):
        """Refresh all ring data."""
        for info in hass.data[DOMAIN].values():
            await info["device_data"].async_refresh_all()
            await info["dings_data"].async_refresh_all()
            await hass.async_add_executor_job(info["history_data"].refresh_all)
            await hass.async_add_executor_job(info["health_data"].refresh_all)

    # register service
    hass.services.async_register(DOMAIN, "update", async_refresh_all)

    return True
示例#24
0
def get_access_token():
    auth = Auth("PyRing/1.0.0", None, update_token)

    if not os.path.exists(token_file):
        try:
            print('   --- Get Ring Access Token ---   \n')
            try:
                email = str(
                    input(style.YELLOW('[+]') + style.RESET(f' Ring Email: ')))
            except KeyboardInterrupt:
                print(u"{}[2J{}[;H".format(chr(27), chr(27)))
                print(style.RED('\n[!]') + style.RESET(' Error: User exit.'))
                print(
                    style.GREEN('[+]') +
                    style.RESET(' Thank you for using PyRing.'))
                print(style.GREEN('[+]') + style.RESET(' Author: Pr0xy07'))
                print(
                    style.GREEN('[+]') + style.RESET(
                        ' If you need any help, contact: [email protected]')
                )
                sys.exit(0)

            try:
                password = str(
                    getpass.getpass(
                        style.YELLOW('[+]') +
                        style.RESET(f' Ring Password: '******'\n[!]') + style.RESET(' Error: User exit.'))
                print(
                    style.GREEN('[+]') +
                    style.RESET(' Thank you for using PyRing.'))
                print(style.GREEN('[+]') + style.RESET(' Author: Pr0xy07'))
                print(
                    style.GREEN('[+]') + style.RESET(
                        ' If you need any help, contact: [email protected]')
                )
                sys.exit(0)

            auth.fetch_token(email, password)
            get_access_token.auth = Auth("PyRing/1.0.0",
                                         json.loads(token_file.read_text()),
                                         update_token)

        except MissingTokenError:
            auth.fetch_token(email, password, two_factor_authentication(email))
            get_access_token.auth = Auth("PyRing/1.0.0",
                                         json.loads(token_file.read_text()),
                                         update_token)
        except:
            print(u"{}[2J{}[;H".format(chr(27), chr(27)))
            print(
                style.RED('\n[!]') + style.RESET(
                    ' Cannot log in with the provided credentials, exiting...')
            )
            print(
                style.GREEN('[+]') +
                style.RESET(' Thank you for using PyRing.'))
            print(style.GREEN('[+]') + style.RESET(' Author: Pr0xy07'))
            print(
                style.GREEN('[+]') + style.RESET(
                    ' If you need any help, contact: [email protected]'))
            sys.exit(0)
    else:
        get_access_token.auth = Auth("PyRing/1.0.0",
                                     json.loads(token_file.read_text()),
                                     update_token)
示例#25
0
logger.addHandler(ch)
logger.addHandler(fh)


# Connecting to RING.com
def token_updated(token):
    cache_file.write_text(json.dumps(token))


def otp_callback():
    auth_code = input("2FA code: ")
    return auth_code


if cache_file.is_file():
    auth = Auth("MyProject/1.0", json.loads(cache_file.read_text()),
                token_updated)
else:
    username = input("Username: "******"Password: "******"MyProject/1.0", None, token_updated)
    try:
        auth.fetch_token(username, password)
    except MissingTokenError:
        auth.fetch_token(username, password, otp_callback())

myring = Ring(auth)
myring.update_data()

fh = fhem.Fhem(fhem_ip, fhem_port)

示例#26
0
def main():

    parser = argparse.ArgumentParser(
        description="Ring Doorbell",
        epilog="https://github.com/tchellomello/python-ring-doorbell",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    parser.add_argument(
        "-u", "--username", dest="username", type=str, help="username for Ring account"
    )

    parser.add_argument(
        "-p", "--password", type=str, dest="password", help="username for Ring account"
    )

    parser.add_argument(
        "--count",
        action="store_true",
        default=False,
        help="count the number of videos on your Ring account",
    )

    parser.add_argument(
        "--download-all",
        action="store_true",
        default=False,
        help="download all videos on your Ring account",
    )

    args = parser.parse_args()
    _header()

    # connect to Ring account
    if cache_file.is_file():
        auth = Auth("RingCLI/0.6", json.loads(cache_file.read_text()), token_updated)
    else:
        if not args.username:
            args.username = input("Username: "******"Password: "******"RingCLI/0.6", None, token_updated)
        try:
            auth.fetch_token(args.username, args.password)
        except MissingTokenError:
            auth.fetch_token(args.username, args.password, input("2FA Code: "))

    ring = Ring(auth)
    ring.update_data()
    devices = ring.devices()
    doorbell = devices["doorbots"][0]

    _bar()

    if args.count:
        print(
            "\tCounting videos linked on your Ring account.\n"
            + "\tThis may take some time....\n"
        )

        events = []
        counter = 0
        history = doorbell.history(limit=100)
        while len(history) > 0:
            events += history
            counter += len(history)
            history = doorbell.history(older_than=history[-1]["id"])

        motion = len([m["kind"] for m in events if m["kind"] == "motion"])
        ding = len([m["kind"] for m in events if m["kind"] == "ding"])
        on_demand = len([m["kind"] for m in events if m["kind"] == "on_demand"])

        print("\tTotal videos: {}".format(counter))
        print("\tDing triggered: {}".format(ding))
        print("\tMotion triggered: {}".format(motion))
        print("\tOn-Demand triggered: {}".format(on_demand))

        # already have all events in memory
        if args.download_all:
            counter = 0
            print(
                "\tDownloading all videos linked on your Ring account.\n"
                + "\tThis may take some time....\n"
            )

            for event in events:
                counter += 1
                filename = _format_filename(event)
                print("\t{}/{} Downloading {}".format(counter, len(events), filename))

                doorbell.recording_download(
                    event["id"], filename=filename, override=False
                )

    if args.download_all and not args.count:
        print(
            "\tDownloading all videos linked on your Ring account.\n"
            + "\tThis may take some time....\n"
        )
        history = doorbell.history(limit=100)

        while len(history) > 0:
            print(
                "\tProcessing and downloading the next" + " videos".format(len(history))
            )

            counter = 0
            for event in history:
                counter += 1
                filename = _format_filename(event)
                print("\t{}/{} Downloading {}".format(counter, len(history), filename))

                doorbell.recording_download(
                    event["id"], filename=filename, override=False
                )

            history = doorbell.history(limit=100, older_than=history[-1]["id"])
示例#27
0
def main():
    if cache_file.is_file():
        auth = Auth("MyProject/1.0d", json.loads(cache_file.read_text()),
                    token_updated)
    else:
        # Comment or Un the following to be prompted or use what we have already set
        #        username = input("Username: "******"Password: "******"MyProjectShared/1.0d", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())
    myring = Ring(auth)
    myring.update_data()  #;print(How To Print All Data)
    devices = myring.devices()  #;print(devices)
    doorbells = devices["doorbots"]
    print(doorbells)
    stickup_cams = devices["stickup_cams"]  #;print(stickup_cams)
    chimes = devices["chimes"]  #;print(chimes)
    #    print( "myring.is_connected" ), # Not valid after python2.7
    #    print( "myring.is_connected", end = '' )
    #    print( myring.is_connected ) # True
    ## Would be nice to esplicitly test that we got connefcted,
    #    p = subprocess.Popen(["sleep", "1"], stdout=subprocess.PIPE); output, err = p.communicate()#; print(output.rstrip(os.linesep)) # Sleep for BreakAbility
    #    p = subprocess.Popen(["sleep", "1"], stdout=subprocess.PIPE); output, err = p.communicate()#; print(output.rstrip(os.linesep)) # Sleep for BreakAbility
    for acamera in list(stickup_cams + doorbells):
        # limit on dev.account_id = 12345678 and print the Account ID: when connecting?
        #    for event in acamera.history(limit=QueueDepth, older_than=6753104150123456789): # ['created_at'] #,'id'] # Older than example
        for event in acamera.history(
                limit=QueueDepth,
                older_than=OlderThan):  # ['created_at'] #,'id']
            #        filename='%s-%s-%s' % (acamera.name.replace(" ","_"), event['created_at'].astimezone(timezone('US/Pacific')).strftime("%Y%m%d.%H%M%S"), event['id']) # from pytz import timezone
            # TODO: ... ... Need a new Ignore: state for cameras that match "-Driveway-" for the neighbors cam.
            # #Or filter on the Account ID: 12345678
            camname = '%s' % acamera.name.replace(
                " ", "_")  # Sanitize Cam Names, of Spaces at least... ...
            cliptime = '%s' % event['created_at'].astimezone(
                timezone(MyTimeZone)).strftime("%Y%m%d.%H%M%S")
            clipyear = '%s' % event['created_at'].astimezone(
                timezone(MyTimeZone)).strftime("%Y")
            clipmonth = '%s' % event['created_at'].astimezone(
                timezone(MyTimeZone)).strftime("%m")
            clipday = '%s' % event['created_at'].astimezone(
                timezone(MyTimeZone)).strftime("%d")
            clipid = '%s' % event['id']
            foldername = BaseDir + "/" + clipyear + "/" + clipmonth + "/" + clipday
            p = subprocess.Popen(["mkdir", "-pv", foldername],
                                 stdout=subprocess.PIPE)
            output, err = p.communicate()
            #	        print(output.rstrip(os.linesep)) # print the result of creating the container folder YYYY/MM/DD # Prints an empty line if dir already exists
            filename = cliptime + "-" + camname + "-" + clipid
            #print(filename)
            filepath = foldername + "/" + filename + ".mp4"
            print(bcolors.OKBLUE + "Fetchin " + filepath + bcolors.ENDC,
                  end='')
            sys.stdout.flush()  # import sys # Force partial line to be printed
            print(
                "\r", end=''
            )  # Carrage return back to top of line for the results to be rewritten
            if not os.path.exists(
                    filepath):  # import os # Test that file does not exist yet
                ## Would like to esplicitly watch for a ^C BREAK from the parent, sometimes that gets ignored and can not abort.
                if acamera.recording_download(event['id'], filename=filepath):
                    print(bcolors.OKGREEN + "Success" + bcolors.ENDC +
                          bcolors.BOLD,
                          end='')
                    #	                subprocess.call(["ls", "-lh", filepath]) # import subprocess #
                    #	                print(subprocess.call(["ls", "-lh", filepath])) # import subprocess # Prints ls output and then "Success 0"(Return Code)?
                    p = subprocess.Popen(["ls", "-lh", filepath],
                                         stdout=subprocess.PIPE)
                    output, err = p.communicate()
                    #	                print("*** Running ls -l command ***\n")
                    #	                print(output), # Does a new line even though we used a comma, otherwise does two new lines, must have a \n within the output
                    #                    print(output.rstrip(os.linesep))
                    # This inline comment no longer works from py2.7 to py3.6 # similar to perl chomp to cleanup /r/n
                    #	                df=os.system("df -h / | grep /") # Not working right?
                    #	                print(df) # when attempting .rstrip(os.linesep) get error AttributeError: 'int' object has no attribute 'rstrip'
                    print(bcolors.UNDERLINE + bcolors.OKGREEN + "#" +
                          bcolors.ENDC)
#                    print(acamera.recording_url(event['id'])) # Could print this into a filename.lnk instead to keep a shareable link? DEBUG
                else:  # acamera.recording_download failed
                    print(bcolors.FAIL + "Failed-" + bcolors.ENDC)
                    print(acamera.recording_url(event['id']))
            else:  # os.path.exists so skip
                print(bcolors.WARNING + "Skipped" + bcolors.ENDC)
示例#28
0
def main():
    configure_logger()
    register_stack_dump()

    global slack
    slack = Slacker(SLACK_API_KEY)

    global worker_thread
    worker_thread = Thread(target=worker_loop, name="Worker Thread")
    worker_thread.daemon = True
    worker_thread.start()

    global s3_client
    s3_client = boto3.client(
        's3',
        aws_access_key_id=AWS_ACCESS_KEY,
        aws_secret_access_key=AWS_SECREY_KEY,
    )

    logger.info("Connecting to Ring API")
    if cache_file.is_file():
        auth = Auth("MyProject/1.0", loads(cache_file.read_text()), token_updated)
    else:
        username = RING_USERNAME
        password = RING_PASSWORD
        auth = Auth("MyProject/1.0", None, token_updated)
        try:
            auth.fetch_token(username, password)
        except MissingTokenError:
            auth.fetch_token(username, password, otp_callback())

    ring = Ring(auth)
    ring.update_data()
    logger.info("Connected to Ring API")

    devices = ring.devices()
    logger.info("Found devices {}".format(devices))

    video_devices = devices["doorbots"] + devices["stickup_cams"]
    logger.info("Watching for events on devices {}".format(video_devices))

    # Init event ids
    for device in video_devices:
        device.latest_id = get_latest_recording(device)["id"]
        logger.info("Found latest event id {} for device {}".format(
            device.latest_id, device))

    # Loop for ever, checking to see if a new video becomes available
    try:
        while True:
            time.sleep(HIST_POLL_TIMEOUT_SECS)

            for device in video_devices:
                event = get_latest_recording(device)
                new_id = event["id"]

                if new_id != device.latest_id:
                    logger.info("Detected a new event for device {}".format(device))
                    device.latest_id = new_id
                    enqueue_event(event, device)

    except KeyboardInterrupt:
        exit(0)
示例#29
0
def getAuth():
    if oauth_file.is_file():
        auth = Auth("MyProject/1.0", json.loads(oauth_file.read_text()), token_updated)
    else:
        sys.exit(f"Authorization file does not exist {oauthFilePath}")
    return auth
示例#30
0
class ring(FhemModule):
    def __init__(self, logger):
        super().__init__(logger)
        self.loop = asyncio.get_event_loop()
        self._username = None
        self._password = ""
        self._token = ""
        self._2facode = None
        self._attr_dingPollInterval = 5
        self._attr_deviceUpdateInterval = 300
        self._history = []
        self._rdevice = None
        self._lastrecording_url = ""
        self._livestreamjson = ""
        self._login_lock = asyncio.Lock()
        self._snapshot = None
        self._attr_list = {
            "deviceUpdateInterval": {
                "default": 300,
                "format": "int"
            },
            "dingPollInterval": {
                "default": 2,
                "format": "int"
            },
        }
        self.set_attr_config(self._attr_list)
        self.set_list_conf = {
            "password": {
                "args": ["password"]
            },
            "2fa_code": {
                "args": ["2facode"]
            },
        }
        self.set_set_config(self.set_list_conf)
        self.stop_dings_loop = threading.Event()
        self.update_dings_thread = None
        return

    async def token_updated(self, token):
        self._token = token
        encrypted_token = utils.encrypt_string(json.dumps(token),
                                               self._reading_encryption_key)
        await fhem.readingsSingleUpdate(self.hash, "token", encrypted_token, 1)

    # FHEM FUNCTION
    async def Define(self, hash, args, argsh):
        await super().Define(hash, args, argsh)
        if len(args) < 5:
            return ("Usage: define rrring fhempy ring <USERNAME>"
                    " <RING_DEVICE_NAME> [<IDENTIFIER>]")
        self._username = args[3]
        self._rdevname = args[4]
        if len(args) > 5:
            self._ridentifier = args[5]
            self.hash["IDENTIFIER"] = args[5]
        else:
            characters = string.ascii_letters + string.digits
            self._ridentifier = "".join(
                random.choice(characters) for _ in range(20))
        self._reading_encryption_key = await fhem.getUniqueId(hash)
        # ring service
        self._ring = None
        # ring doorbell/chime/... device
        self._rdevice = None
        self.hash["USERNAME"] = args[3]
        self.hash["RINGDEVICE"] = args[4]
        self.create_async_task(self.ring_login())

    async def ring_login(self):
        async with self._login_lock:
            if self._token == "":
                token_reading = await fhem.ReadingsVal(self.hash["NAME"],
                                                       "token", "")
                if token_reading != "":
                    token_reading = utils.decrypt_string(
                        token_reading, self._reading_encryption_key)
                    self._token = json.loads(token_reading)
            if self._password == "":
                self._password = await fhem.ReadingsVal(
                    self.hash["NAME"], "password", "")
                if self._password != "":
                    self._password = utils.decrypt_string(
                        self._password, self._reading_encryption_key)
            try:
                ret = await utils.run_blocking(
                    functools.partial(self.blocking_login))
                if ret:
                    await fhem.readingsSingleUpdate(self.hash, "state", ret, 1)
                    return
                await fhem.readingsSingleUpdate(self.hash, "state",
                                                "connected", 1)
                # start update loop, we are already in a task, therefore no need to create
                await self.update_loop()
            except Exception:
                await fhem.readingsSingleUpdate(self.hash, "state",
                                                "Login failed", 1)
                self.logger.error("Login failed")

    async def update_loop(self):
        try:
            await utils.run_blocking(functools.partial(self._ring.update_data))
            devices = await utils.run_blocking(
                functools.partial(self._ring.devices))
            for dev_type in devices:
                for dev in devices[dev_type]:
                    if dev.name == self._rdevname:
                        self._rdevice = dev

            if self._rdevice is None:
                await fhem.readingsSingleUpdate(self.hash, "state",
                                                "device not found", 1)
                return

            if self._rdevice is not None and self._rdevice.has_capability(
                    "volume"):
                self.set_list_conf["volume"] = {
                    "args": ["volume"],
                    "params": {
                        "volume": {
                            "format": "int"
                        }
                    },
                    "options": "slider,0,1,10",
                }
            self.set_set_config(self.set_list_conf)

            await self.update_readings()

            self.create_async_task(self.update_dings_loop())

            while True:
                try:
                    await utils.run_blocking(
                        functools.partial(self.poll_device))
                    await self.update_readings()
                    # handle history
                    if len(self._history) > 0:
                        i = 1
                        for event in self._history:
                            await self.update_history_readings(event, i)
                            i += 1
                except Exception:
                    self.logger.exception("Failed to poll devices")
                await asyncio.sleep(self._attr_deviceUpdateInterval)
        except CancelledError:
            pass
        except Exception:
            self.logger.exception("Failed to update devices")

    async def update_dings_loop(self):
        try:
            self.update_dings_thread = await utils.run_blocking(
                functools.partial(self.update_dings_loop_thread))
        except CancelledError:
            pass

    def update_dings_loop_thread(self):
        alert_active = 0
        while True:
            try:
                if self.stop_dings_loop.is_set():
                    return

                self.poll_dings()
                # handle alerts
                alerts = self._ring.active_alerts()
                self.logger.debug("Received dings: " + str(alerts))
                if len(alerts) > 0:
                    for alert in alerts:
                        if alert["doorbot_id"] == self._rdevice.id:
                            alert_active = 1
                            asyncio.run_coroutine_threadsafe(
                                self.update_alert_readings(alert),
                                self.loop).result()
                elif alert_active == 1:
                    alert_active = 0
                    asyncio.run_coroutine_threadsafe(
                        fhem.readingsSingleUpdateIfChanged(
                            self.hash, "state", "connected", 1),
                        self.loop,
                    ).result()
                    self.poll_device()
                    asyncio.run_coroutine_threadsafe(self.update_readings(),
                                                     self.loop).result()
            except Exception:
                self.logger.exception("Failed to poll dings...")
                self.blocking_login()
            time.sleep(self._attr_dingPollInterval)

    async def update_alert_readings(self, alert):
        await fhem.readingsBeginUpdate(self.hash)
        await fhem.readingsBulkUpdate(self.hash, "alert_id", alert["id"])
        await fhem.readingsBulkUpdate(self.hash, "alert_kind", alert["kind"])
        await fhem.readingsBulkUpdate(self.hash, "alert_sip_to",
                                      alert["sip_to"])
        await fhem.readingsBulkUpdate(self.hash, "alert_sip_token",
                                      alert["sip_token"])
        await fhem.readingsBulkUpdate(self.hash, "alert_doorbot_id",
                                      alert["doorbot_id"])
        await fhem.readingsBulkUpdate(self.hash, "state", alert["kind"])
        await fhem.readingsEndUpdate(self.hash, 1)

    async def update_history_readings(self, event, idx):
        await fhem.readingsBeginUpdate(self.hash)
        await fhem.readingsBulkUpdateIfChanged(self.hash,
                                               "history_" + str(idx) + "_id",
                                               event["id"])
        await fhem.readingsBulkUpdateIfChanged(self.hash,
                                               "history_" + str(idx) + "_kind",
                                               event["kind"])
        await fhem.readingsBulkUpdateIfChanged(
            self.hash, "history_" + str(idx) + "_answered", event["answered"])
        await fhem.readingsBulkUpdateIfChanged(
            self.hash, "history_" + str(idx) + "_created_at",
            event["created_at"])
        await fhem.readingsEndUpdate(self.hash, 1)

    async def update_readings(self):
        await fhem.readingsBeginUpdate(self.hash)
        try:
            await fhem.readingsBulkUpdateIfChanged(self.hash, "address",
                                                   self._rdevice.address)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "family",
                                                   self._rdevice.family)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "device_id",
                                                   self._rdevice.device_id)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "id",
                                                   self._rdevice.id)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "model",
                                                   self._rdevice.model)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "firmware",
                                                   self._rdevice.firmware)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "latitude",
                                                   self._rdevice.latitude)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "longitude",
                                                   self._rdevice.longitude)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "kind",
                                                   self._rdevice.kind)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "name",
                                                   self._rdevice.name)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "timezone",
                                                   self._rdevice.timezone)
            await fhem.readingsBulkUpdateIfChanged(self.hash, "wifi_name",
                                                   self._rdevice.wifi_name)
            await fhem.readingsBulkUpdateIfChanged(
                self.hash, "wifi_signal_strength",
                self._rdevice.wifi_signal_strength)
            await fhem.readingsBulkUpdateIfChanged(
                self.hash, "wifi_signal_category",
                self._rdevice.wifi_signal_category)
            await self.update_if_available("battery_life")
            await self.update_if_available("existing_doorbell_type")
            await self.update_if_available("existing_doorbell_type_enabled")
            await self.update_if_available("existing_doorbell_type_duration")
            await self.update_if_available("subscribed")
            await self.update_if_available("subscribed_motion")
            await self.update_if_available("has_subscription")
            await self.update_if_available("volume")
            await self.update_if_available("connection_status")
            if (self._rdevice.family == "doorbots"
                    or self._rdevice.family == "authorized_doorbots"):
                await self.update_if_available("last_recording_id")
                await fhem.readingsBulkUpdateIfChanged(self.hash,
                                                       "last_recording_url",
                                                       self._lastrecording_url)
                if self._livestreamjson != "":
                    await fhem.readingsBulkUpdateIfChanged(
                        self.hash, "livestream_json",
                        json.dumps(self._livestreamjson))
                if self._snapshot:
                    snapshot = ('<html><img src="data:image/png,' +
                                self._snapshot + '"/></html>')
                    await fhem.readingsBulkUpdateIfChanged(
                        self.hash, "snapshot", snapshot)
        except Exception:
            self.logger.exception(
                "Failed to update readings, please report here: https://forum.fhem.de/index.php/topic,117381"
            )
        await fhem.readingsEndUpdate(self.hash, 1)

    async def update_if_available(self, reading):
        if hasattr(self._rdevice, reading):
            await fhem.readingsBulkUpdateIfChanged(
                self.hash, reading, getattr(self._rdevice, reading))

    def poll_dings(self):
        self._ring.update_dings()

    def poll_device(self):
        self._rdevice.update_health_data()
        self._ring.update_data()
        self._history = []
        if (self._rdevice.family == "doorbots"
                or self._rdevice.family == "authorized_doorbots"):
            # disable it, as it creates a lot of history entries
            # self._livestreamjson = self._rdevice.live_streaming_json
            for event in self._rdevice.history(limit=5):
                self._history.append(event)
            self._lastrecording_url = self._rdevice.recording_url(
                self._rdevice.last_recording_id)
            if self._lastrecording_url is False:
                self.blocking_login()
            # self._snapshot = self._rdevice.get_snapshot(retries=10)

    def blocking_login(self):
        def token_updater(token):
            asyncio.run_coroutine_threadsafe(self.token_updated(token),
                                             self.loop).result()

        if self._token != "":
            self._auth = Auth(self._ridentifier + "/1.0", self._token,
                              token_updater)
        else:
            if self._password != "":
                self._auth = Auth(self._ridentifier + "/1.0", None,
                                  token_updater)
                if self._2facode:
                    self._auth.fetch_token(self._username, self._password,
                                           self._2facode)
                else:
                    try:
                        self._auth.fetch_token(self._username, self._password)
                    except AccessDeniedError:
                        return "AccessDenied: wrong username or password"
                    except MissingTokenError:
                        return "please set 2fa_code"
            else:
                return "please set password"
        self._ring = Ring(self._auth)

    async def set_volume(self, hash, params):
        new_vol = params["volume"]
        self.create_async_task(self.set_volume_task(new_vol))

    async def set_volume_task(self, new_volume):
        await utils.run_blocking(
            functools.partial(self.set_volume_blocking, new_volume))
        await self.update_readings()

    def set_volume_blocking(self, new_volume):
        self._rdevice.volume = new_volume

    async def set_password(self, hash, params):
        self._password = params["password"]
        encrypted_password = utils.encrypt_string(self._password,
                                                  self._reading_encryption_key)
        await fhem.readingsSingleUpdateIfChanged(self.hash, "password",
                                                 encrypted_password, 1)
        self.create_async_task(self.ring_login())

    async def set_2fa_code(self, hash, params):
        self._2facode = params["2facode"]
        self.create_async_task(self.ring_login())

    async def Undefine(self, hash):
        if self.update_dings_thread:
            self.update_dings_thread.cancel()
        self.stop_dings_loop.set()
        await super().Undefine(hash)