it isnt that hard. with the info you gave in this topic i created a bit more code.
just paste this at the end from your browns app:
#################################################################
# so the sensor is there and updating, so lets make sure a #
# a script will run to turn on the TV #
#################################################################
self.run_at(self.start_game,next_game_time - datetime.timedelta(minutes= self.args["offset_script"],channel = channel)
def start_game(self,kwargs):
#################################################################
# so its time to turn on the TV so lets start the script with #
# the name of the channel #
#################################################################
self.turn_on("script." + kwargs["channel"])
#################################################################
# and we want to start an automation some time after the script #
# has been started #
#################################################################
self.run_in(self.start_automation,self.args["seconds_automation_after_script"])
def start_automation(self,kwargs)
#################################################################
# so its time to start the automation #
#################################################################
if "automation_name" in self.args:
self.turn_on(self.args["automation_name"])
and add these last 3 lines to your browns.yaml
browns:
module: browns
class: browns
offset_script: 15 # in minutes
seconds_automation_after_script: 600 # in seconds
automation_name: automation.browns_football
now all you need to make sure that the script is there and the automation.
i never work with scripts or automations, but i assume that you can find your scripts and automations in your statepage and the have names like this:
the only problem that can be there is that the script entity names are probably in lower case (please check) if so you need to change 1 more line in the code.
Yes you are correct, the states page is lower case but the friendly name is uppercase (Iām not sure if it matters)
Iāll gladly give it a go!
Thanks @renetode I appreciate your help more then you know! I honestly try not to bother people anymore then I need too.
Iām really trying to learn from all of these experiences so I can inturn pay it forward. I spend hours each day researching and looking at posts but mostly get no where. But itās people like you and @petro and others that reach out and go above and beyond to help a stranger out. And in turn I feel like I learn a bit more each time.
This community is the best with some of the smartest, kindest individuals in the world and Iām truly blessed to be a part of it!
@petro, I still can use you code for other things that I want to do with my sensor! Your hard work will still be very useful! Is there a way to show the time to the front end without the 0 in front of the time like 1:00 PM instead of 01:00 PM?
people do love to help you, because you really show appreciation and way more then the usual thanks
i am glad i can help you to learn things.
i did overestimate your capabilities maybe a bit and did let you swim, but it seems that that worked out quite nice, because it helped you to learn
because the scripts are lowercase and the website gives it as uppercase you need to change this line:
its probably not neccesary, but to make sure, please restart appdaemon after you changed all and look at the logs if you see anything strange.
edit: i am pretty confident that this works, but i never started scripts or automations from AD, so please keep your fingers crossed that it works as expected
restarting now and my fingers are crossed!, I always want people to know that they are appreciated I see way too many people here complain when things donāt work as expected or when thereās breaking changes. I just shake my head and donāt understand why, this is a free opensource project that is completely awesome. Since stumbling upon Home Assistant my home automation has done so much good, fun and useful things that I could never begin to imagine or afford without it. I has opened my eyes to the possibilities that can be done that I never dreamed of. I can see where the future is going and I canāt wait to get there!
Yeah, are you using the sensor.time sensor? If so, add this sensor template and hide the other one:
sensor:
- platform: template
sensors:
pretty_time:
value_template: >
{% set ct = states('sensor.date__time') %}
{% set ct = as_timestamp(strptime(ct,'%Y-%m-%d, %H:%M')) %}
{% set ct = ct | timestamp_custom("%H:%M %p") %}
{{ ct[1:] if ct.startswith('0') else ct }}
first line gets the string from the date__time sensor
second line turns it into a timestamp (number of seconds from jan 1st 1970)
third line makes it into a custom string. You may need to turn %H into %I. I forget which one is 24/hr format and which one is 12hr format. Pretty sure %H is 12 hour.
fourth line checks to see if the time starts with a zero. If it does, output everything past the zero. Otherwise, keep it.
The 4th line needs to be written that way because the modifiers for custom timestamps are not allowed. In python, there is a way to remove leading zeros when outputting time. For some reason, that method doesnāt work in jinja templates.
For some reason all of my addons turned off tonight, so I switched them back on then restarted hass.
now for some reason my sensor.browns and my automation is not showing up do you have any ideas why?
OMG, I think they change the schedule site, im about to cryā¦ damn
if I get time next week, I might give this site a go, this does show what I need to find i think?
###########################################################################################
# #
# Rene Tode ( [email protected] ) #
# #
# 2018/10/07 Germany #
# #
# #
# an app to that creates a sensor out of data collected from #
# https://www.clevelandbrowns.com/schedule/ #
# #
###########################################################################################
import appdaemon.plugins.hass.hassapi as hass
import datetime
import time
import requests
from socket import timeout
from bs4 import BeautifulSoup
class browns(hass.Hass):
def initialize(self):
#################################################################
# when initialising the sensor needs to be imported #
# but we need to run the same code again to get the next values #
# thats why i only start the call_back from here #
#################################################################
self.get_values(self)
def get_values(self,kwargs):
#################################################################
# first we set some values, this could be done in the yaml #
# but this app is specialized and will only work for this #
# webpage, so why bother #
#################################################################
self.url = "https://www.clevelandbrowns.com/schedule/"
self.sensorname = "sensor.browns"
self.friendly_name = "Next game from Cleveland Browns"
next_game_time = None
#################################################################
# now we read the webpage #
#################################################################
try:
response = requests.get(self.url,timeout=10)
except:
self.log("i couldnt read the browns schedule page")
return
page = response.content
#################################################################
# now that we got the webpage we make the data readable #
#################################################################
soup = BeautifulSoup(page, "html.parser")
#################################################################
# in the google chrome console we are going down the tree from #
# body. every time an indention is visible we add the next #
# element. untill we see main, which contains a lot of section #
# elements. nextSibling makes us go to the next element on the #
# same level. untill we reach the table containing the schedule #
# cards. some invisible empty siblings make that we need more #
# rimes nextSibling then the amount of sections #
#################################################################
cards_table = soup.body.div.main.section.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling
#################################################################
# to see if we got the right data we log it. uncomment when #
# you expect that the webpage is changed #
#self.log(cards_table) #
#################################################################
#################################################################
# now we find the first card inside the table #
#################################################################
first_card = cards_table.div.div
#################################################################
# the first card is the title card containing "regular season" #
# now we are going to loop to the cards following that first 1 #
#################################################################
for schedule_card in first_card.find_next_siblings():
#############################################################
# lets find the date we want out of the card #
#############################################################
try:
game_start = schedule_card.div["data-gametime"]
except:
#########################################################
# there is no date found in this card (probably an add) #
#########################################################
game_start = ""
#############################################################
# if we find a date, then we need to translate the date to #
# a time we can compare. in this case we find a date like #
# like this 2018-09-09T17:00:00Z which is %Y-%m-%dT%H:%M:%S #
# (python datetime lib docs tell us that) #
#############################################################
if game_start != "":
game_time = datetime.datetime.strptime(game_start,"%Y-%m-%dT%H:%M:%SZ") + datetime.timedelta(hours= -4)
#########################################################
# find out if this date is in the future #
#########################################################
if game_time > datetime.datetime.now():
#####################################################
# check if we didnt find one before, when not set it#
#####################################################
if next_game_time == None:
next_game_time = game_time
#################################################
# now that we know that this is the next game #
# lets also lookup the opponent in the card #
# it will make a nice attribute for the sensor #
# to remove all whitespace we use strip() #
# again we can find that by looking at the #
# google chrome console #
#################################################
opponent = schedule_card.div.div.nextSibling.nextSibling.p.nextSibling.nextSibling.string.strip()
#################################################
# and we want to find the channel that it will #
# be on. #
#################################################
channel = schedule_card.div.div.nextSibling.nextSibling.div.nextSibling.nextSibling.div.div.span.nextSibling.nextSibling.string.strip()
#################################################################
# now we got all data we need but the date isnt what we need #
# we translate that again to the timeformat we want to see #
# for the HA sensor #
#################################################################
next_game_str = next_game_time.strftime("%I:%M %p %m/%d/%y")
#################################################################
# now we got all info we need and we can create a sensor. #
# the first time that the code is run it will create a warning #
# that the sensor doesnt exist. if we see that in the log we #
# know that the sensor is created. #
#################################################################
self.set_state(self.sensorname, state = next_game_str, attributes = {"friendly_name": self.friendly_name,"Opponent": opponent,"Channel": channel})
#################################################################
# now al we need to do is make sure that the sensor stays up to #
# date. we could check the webpage every minute, but that would #
# be unneccesary traffic. we dont know exactly when the webpage #
# is updated, we need to use a short time after the game, but #
# we dont want it to be too long #
# if the sensor isnt up to date, just check the page, restart #
# the app and or change the extra time we now add #
#################################################################
update_time = next_game_time + datetime.timedelta(hours= 4)
#################################################################
# so we got a time that we want to update the sensor. so we run #
# this code again at that time. #
#################################################################
self.run_at(self.get_values,update_time)
#################################################################
# so the sensor is there and updating, so lets make sure a #
# a script will run to turn on the TV #
#################################################################
self.run_at(self.start_game,next_game_time - datetime.timedelta(minutes= self.args["offset_script"],channel = channel)
def start_game(self,kwargs):
#################################################################
# so its time to turn on the TV so lets start the script with #
# the name of the channel #
#################################################################
self.turn_on("script." + kwargs["channel"].lower())
#################################################################
# and we want to start an automation some time after the script #
# has been started #
#################################################################
self.run_in(self.start_automation,self.args["seconds_automation_after_script"])
def start_automation(self,kwargs):
#################################################################
# so its time to start the automation #
#################################################################
if "automation_name" in self.args:
self.turn_on(self.args["automation_name"])
I changed the lines, but they changed the Cleveland Browns.com/schedule web sight completely so now all the information is not on the page like it was. Iām going to have to try that new one I posted above because it does show all the info and more the old one had. I canāt believe it lol.
I might look into trying to pull the info from google calendar next season that way it will be more stable each season. The link above letās you import to your Calendar.
ok I found a few things, but im still getting errors. Im trying! ###########################################################################################
# #
# Rene Tode ( [email protected] ) #
# #
# 2018/10/07 Germany #
# #
# #
# an app to that creates a sensor out of data collected from #
# https://www.clevelandbrowns.com/schedule/ #
# #
###########################################################################################
import appdaemon.plugins.hass.hassapi as hass
import datetime
import time
import requests
from socket import timeout
from bs4 import BeautifulSoup
class browns(hass.Hass):
def initialize(self):
#################################################################
# when initialising the sensor needs to be imported #
# but we need to run the same code again to get the next values #
# thats why i only start the call_back from here #
#################################################################
self.get_values(self)
def get_values(self,kwargs):
#################################################################
# first we set some values, this could be done in the yaml #
# but this app is specialized and will only work for this #
# webpage, so why bother #
#################################################################
self.url = "https://www.clevelandbrowns.com/schedule/"
self.sensorname = "sensor.browns"
self.friendly_name = "Next game from Cleveland Browns"
next_game_time = None
#################################################################
# now we read the webpage #
#################################################################
try:
response = requests.get(self.url,timeout=10)
except:
self.log("i couldnt read the browns schedule page")
return
page = response.content
#################################################################
# now that we got the webpage we make the data readable #
#################################################################
soup = BeautifulSoup(page, "html.parser")
#################################################################
# in the google chrome console we are going down the tree from #
# body. every time an indention is visible we add the next #
# element. untill we see main, which contains a lot of section #
# elements. nextSibling makes us go to the next element on the #
# same level. untill we reach the table containing the schedule #
# cards. some invisible empty siblings make that we need more #
# rimes nextSibling then the amount of sections #
#################################################################
cards_table = soup.body.div.main.section.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling
#################################################################
# to see if we got the right data we log it. uncomment when #
# you expect that the webpage is changed #
#self.log(cards_table)
#################################################################
#################################################################
# now we find the first card inside the table #
#################################################################
first_card = cards_table.div.div
#################################################################
# the first card is the title card containing "regular season" #
# now we are going to loop to the cards following that first 1 #
#################################################################
for schedule_card in first_card.find_next_siblings():
#############################################################
# lets find the date we want out of the card #
#############################################################
try:
game_start = schedule_card.div["data-gametime"]
except:
#########################################################
# there is no date found in this card (probably an add) #
#########################################################
game_start = ""
#############################################################
# if we find a date, then we need to translate the date to #
# a time we can compare. in this case we find a date like #
# like this 2018-09-09T17:00:00Z which is %Y-%m-%dT%H:%M:%S #
# (python datetime lib docs tell us that) #
#############################################################
if game_start != "":
game_time = datetime.datetime.strptime(game_start,"%Y-%m-%dT%H:%M:%SZ") + datetime.timedelta(hours= -4)
#########################################################
# find out if this date is in the future #
#########################################################
if game_time > datetime.datetime.now():
#####################################################
# check if we didnt find one before, when not set it#
#####################################################
if next_game_time == None:
next_game_time = game_time
#################################################
# now that we know that this is the next game #
# lets also lookup the opponent in the card #
# it will make a nice attribute for the sensor #
# to remove all whitespace we use strip() #
# again we can find that by looking at the #
# google chrome console #
#################################################
opponent = schedule_card.div.div.nextSibling.nextSibling.p.nextSibling.nextSibling.string.strip()
#################################################
# and we want to find the channel that it will #
# be on. #
#################################################
channel = schedule_card.div.div.nextSibling.nextSibling.div.nextSibling.nextSibling.div.div.span.nextSibling.nextSibling.string.strip()
#################################################################
# now we got all data we need but the date isnt what we need #
# we translate that again to the timeformat we want to see #
# for the HA sensor #
#################################################################
next_game_str = next_game_time.strftime("%I:%M %p %m/%d/%y")
#################################################################
# now we got all info we need and we can create a sensor. #
# the first time that the code is run it will create a warning #
# that the sensor doesnt exist. if we see that in the log we #
# know that the sensor is created. #
#################################################################
self.run_at(self.start_game,next_game_time - datetime.timedelta(minutes= self.args["offset_script"]),channel = channel)
#################################################################
# now al we need to do is make sure that the sensor stays up to #
# date. we could check the webpage every minute, but that would #
# be unneccesary traffic. we dont know exactly when the webpage #
# is updated, we need to use a short time after the game, but #
# we dont want it to be too long #
# if the sensor isnt up to date, just check the page, restart #
# the app and or change the extra time we now add #
#################################################################
update_time = next_game_time + datetime.timedelta(hours= 4)
#################################################################
# so we got a time that we want to update the sensor. so we run #
# this code again at that time. #
#################################################################
self.run_at(self.get_values,update_time)
#################################################################
# so the sensor is there and updating, so lets make sure a #
# a script will run to turn on the TV #
#################################################################
self.run_at(self.start_game,next_game_time - datetime.timedelta(minutes= self.args["offset_script"],channel = channel)
def start_game(self,kwargs):
#################################################################
# so its time to turn on the TV so lets start the script with #
# the name of the channel #
#################################################################
self.turn_on("script." + kwargs["channel"].lower())
#################################################################
# and we want to start an automation some time after the script #
# has been started #
#################################################################
self.run_in(self.start_automation,self.args["seconds_automation_after_script"])
def start_automation(self,kwargs):
#################################################################
# so its time to start the automation #
#################################################################
if "automation_name" in self.args:
self.turn_on(self.args["automation_name"])