diff --git a/README.md b/README.md
index 24f3200..02778d1 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@
+
本应用可以帮助你将国网的电费、用电量数据接入homeassistant,实现实时追踪家庭用电量情况;并且可以将每日用电量保存到数据库,历史有迹可循。具体提供两类数据:
@@ -20,6 +21,8 @@
| sensor.electricity_charge_balance | 预付费显示电费余额,反之显示上月应交电费,单位元 |
| sensor.yearly_electricity_usage | 今年总用电量,单位KWH、度。 |
| sensor.yearly_electricity_charge | 今年总用电费用,单位元 |
+ | sensor.month_electricity_usage | 最近一天用电量,单位KWH、度。属性含present_date(查询电量代表的日期)|
+ | sensor.month_electricity_charge | 上月总用电费用,单位元 属性含present_date(查询电量代表的日期)| |
2. 可选,近三十天每日用电量数据(mongodb数据库),例如:

@@ -162,7 +165,7 @@
```bash
git clone https://github.com/ARC-MX/sgcc_electricity_new.git
- cd sgcc_electricity
+ cd sgcc_electricity_new
```
2. 参考example.env编写.env文件
@@ -180,7 +183,7 @@
### 3)方法三:不安装docker,安装python环境后直接运行:
-克隆仓库之后,参考Dockerfile的命令,``自行配置安装chrome浏览器和selenium浏览器驱动``,安装mongodb,将example.env文件复制为.env文件到scripts文件夹下,然后运行main.py文件。
+克隆仓库之后,参考Dockerfile的命令,``自行配置安装chrome浏览器和selenium浏览器驱动 ``,安装mongodb,将example.env文件复制为.env文件到scripts文件夹下,然后运行main.py文件。
### 4)方法四:使用可视化docker管理工具[portainer]([url](https://www.portainer.io/))部署:
@@ -198,7 +201,6 @@
- 如果你有一个户号,参照以下配置:
-```yaml
# Example configuration.yaml entry
# 文件中只能有一个template
template:
@@ -215,7 +217,7 @@ template:
state_class: total
unit_of_measurement: "CNY"
device_class: monetary
-
+
- trigger:
- platform: event
event_type: "state_changed"
@@ -231,7 +233,39 @@ template:
state_class: measurement
unit_of_measurement: "kWh"
device_class: energy
-
+
+ - trigger:
+ - platform: event
+ event_type: "state_changed"
+ event_data:
+ entity_id: sensor.month_electricity_usage
+ sensor:
+ - name: month_electricity_usage_entity
+ unique_id: month_electricity_usage_entity
+ state: "{{ states('sensor.month_electricity_usage') }}"
+ attributes:
+ present_date: "{{ state_attr('sensor.month_electricity_usage', 'present_date') }}"
+ last_updated: "{{ state_attr('sensor.month_electricity_usage', 'month_updated') }}"
+ state_class: measurement
+ unit_of_measurement: "kWh"
+ device_class: energy
+
+ - trigger:
+ - platform: event
+ event_type: "state_changed"
+ event_data:
+ entity_id: sensor.month_electricity_charge
+ sensor:
+ - name: month_electricity_charge_entity
+ unique_id: month_electricity_charge_entity
+ state: "{{ states('sensor.month_electricity_charge') }}"
+ attributes:
+ present_date: "{{ state_attr('sensor.month_electricity_charge', 'present_date') }}"
+ last_updated: "{{ state_attr('sensor.month_electricity_charge', 'month_updated') }}"
+ state_class: measurement
+ unit_of_measurement: "CNY"
+ device_class: monetary
+
- trigger:
- platform: event
event_type: "state_changed"
@@ -257,7 +291,6 @@ template:
state_class: total
unit_of_measurement: "CNY"
device_class: monetary
-```
- 如果你有多个户号,每个户号参照[configuration.yaml](template/configuration.yaml)配置。
diff --git a/assets/image-20240514.jpg b/assets/image-20240514.jpg
new file mode 100644
index 0000000..5bbbd9b
Binary files /dev/null and b/assets/image-20240514.jpg differ
diff --git a/scripts/const.py b/scripts/const.py
index c078881..fea5fef 100644
--- a/scripts/const.py
+++ b/scripts/const.py
@@ -12,7 +12,9 @@
BALANCE_SENSOR_NAME = "sensor.electricity_charge_balance"
DAILY_USAGE_SENSOR_NAME = "sensor.last_electricity_usage"
YEARLY_USAGE_SENSOR_NAME = "sensor.yearly_electricity_usage"
-YEARLY_CHARGE_SENESOR_NAME = "sensor.yearly_electricity_charge"
+YEARLY_CHARGE_SENSOR_NAME = "sensor.yearly_electricity_charge"
+MONTH_USAGE_SENSOR_NAME = "sensor.month_electricity_usage"
+MONTH_CHARGE_SENSOR_NAME = "sensor.month_electricity_charge"
BALANCE_UNIT = "CNY"
USAGE_UNIT = "KWH"
diff --git a/scripts/data_fetcher.py b/scripts/data_fetcher.py
index 8b9bb2b..2cdba02 100644
--- a/scripts/data_fetcher.py
+++ b/scripts/data_fetcher.py
@@ -269,13 +269,13 @@ def _fetch(self):
balance_list = self._get_electric_balances(driver, user_id_list) #
time.sleep(self.RETRY_WAIT_TIME_OFFSET_UNIT)
### get data except electricity charge balance
- last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list = self._get_other_data(driver, user_id_list)
+ last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list, month_list, month_usage_list, month_charge_list = self._get_other_data(driver, user_id_list)
time.sleep(self.RETRY_WAIT_TIME_OFFSET_UNIT)
driver.quit()
logging.info("Webdriver quit after fetching data successfully.")
logging.info("浏览器已退出")
- return user_id_list, balance_list, last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list
+ return user_id_list, balance_list, last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list, month_list, month_usage_list, month_charge_list
finally:
driver.quit()
@@ -380,7 +380,9 @@ def _get_other_data(self, driver, user_id_list):
last_daily_usage_list = []
yearly_usage_list = []
yearly_charge_list = []
-
+ month_list = []
+ month_charge_list = []
+ month_usage_list = []
# swithc to electricity usage page
driver.get(ELECTRIC_USAGE_URL)
@@ -400,6 +402,14 @@ def _get_other_data(self, driver, user_id_list):
logging.info(
f"Get year power charge for {user_id_list[i - 1]} successfully, yealrly charge is {yearly_charge} CNY")
+ # get month usage
+ month, month_usage, month_charge = self._get_month_usage(driver)
+ if month is None:
+ logging.error(f"Get month power usage for {user_id_list[i - 1]} failed, pass")
+ else:
+ for m in range(len(month)):
+ logging.info(
+ f"Get month power charge for {user_id_list[i - 1]} successfully, {month[m]} usage is {month_usage[m]} KWh, charge is {month_charge[m]} CNY.")
# get yesterday usage
last_daily_datetime, last_daily_usage = self._get_yesterday_usage(driver)
@@ -417,6 +427,9 @@ def _get_other_data(self, driver, user_id_list):
last_daily_usage_list.append(last_daily_usage)
yearly_charge_list.append(yearly_charge)
yearly_usage_list.append(yearly_usage)
+ month_list.append(month[-1])
+ month_charge_list.append(month_charge[-1])
+ month_usage_list.append(month_usage[-1])
# switch to next user id
if i != len(user_id_list):
@@ -425,7 +438,7 @@ def _get_other_data(self, driver, user_id_list):
self._click_button(driver, By.XPATH,
f"//body/div[@class='el-select-dropdown el-popper']//ul[@class='el-scrollbar__view el-select-dropdown__list']/li[{i + 1}]")
- return last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list
+ return last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list, month_list, month_usage_list, month_charge_list
def _get_user_ids(self, driver):
@@ -496,6 +509,31 @@ def _get_yesterday_usage(self, driver):
except:
return None
+ def _get_month_usage(self, driver):
+ """获取每月用电量"""
+
+ try:
+ self._click_button(driver, By.XPATH, "//div[@class='el-tabs__nav is-top']/div[@id='tab-first']")
+ time.sleep(self.RETRY_WAIT_TIME_OFFSET_UNIT)
+ # wait for month displayed
+ target = driver.find_element(By.CLASS_NAME, "total")
+ WebDriverWait(driver, self.DRIVER_IMPLICITY_WAIT_TIME).until(EC.visibility_of(target))
+ month_element = driver.find_element(By.XPATH, "//*[@id='pane-first']/div[1]/div[2]/div[2]/div/div[3]/table/tbody").text
+ month_element = month_element.split("\n")
+ month_element.remove("MAX")
+ month_element = np.array(month_element).reshape(-1, 3)
+ # 将每月的用电量保存为List
+ month = []
+ usage = []
+ charge = []
+ for i in range(len(month_element)):
+ month.append(month_element[i][0])
+ usage.append(month_element[i][1])
+ charge.append(month_element[i][2])
+ return month, usage, charge
+ except:
+ return None,None,None
+
# 增加储存30天用电量的到mongodb的函数
def save_30_days_usage(self, driver, user_id):
"""储存30天用电量"""
diff --git a/scripts/main.py b/scripts/main.py
index 5efd39c..cc427ca 100644
--- a/scripts/main.py
+++ b/scripts/main.py
@@ -54,20 +54,22 @@ def main():
def run_task(data_fetcher: DataFetcher, sensor_updator: SensorUpdator):
try:
- user_id_list, balance_list, last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list = data_fetcher.fetch()
-
+ user_id_list, balance_list, last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list, month_list, month_usage_list, month_charge_list = data_fetcher.fetch()
+ # user_id_list, balance_list, last_daily_date_list, last_daily_usage_list, yearly_charge_list, yearly_usage_list, month_list, month_usage_list, month_charge_list = ['123456'],[58.1],['2024-05-12'],[3.0],['239.1'],['533'],['2024-04-01-2024-04-30'],['118'],['52.93']
for i in range(0, len(user_id_list)):
profix = f"_{user_id_list[i]}" if len(user_id_list) > 1 else ""
if balance_list[i] is not None:
sensor_updator.update(BALANCE_SENSOR_NAME + profix, None, balance_list[i], BALANCE_UNIT)
if last_daily_usage_list[i] is not None:
- sensor_updator.update(DAILY_USAGE_SENSOR_NAME + profix, last_daily_date_list[i],
- last_daily_usage_list[i], USAGE_UNIT)
+ sensor_updator.update(DAILY_USAGE_SENSOR_NAME + profix, last_daily_date_list[i], last_daily_usage_list[i], USAGE_UNIT)
if yearly_usage_list[i] is not None:
sensor_updator.update(YEARLY_USAGE_SENSOR_NAME + profix, None, yearly_usage_list[i], USAGE_UNIT)
if yearly_charge_list[i] is not None:
- sensor_updator.update(YEARLY_CHARGE_SENESOR_NAME + profix, None, yearly_charge_list[i], BALANCE_UNIT)
-
+ sensor_updator.update(YEARLY_CHARGE_SENSOR_NAME + profix, None, yearly_charge_list[i], BALANCE_UNIT)
+ if month_charge_list[i] is not None:
+ sensor_updator.update(MONTH_CHARGE_SENSOR_NAME + profix, month_list[i], month_charge_list[i], BALANCE_UNIT, month=True)
+ if month_usage_list[i] is not None:
+ sensor_updator.update(MONTH_USAGE_SENSOR_NAME + profix, month_list[i], month_usage_list[i], USAGE_UNIT, month=True)
logging.info("state-refresh task run successfully!")
except Exception as e:
logging.error(f"state-refresh task failed, reason is {e}")
diff --git a/scripts/sensor_updator.py b/scripts/sensor_updator.py
index 60fc489..60e3f48 100644
--- a/scripts/sensor_updator.py
+++ b/scripts/sensor_updator.py
@@ -13,7 +13,7 @@ def __init__(self, base_url: str, token: str):
self.base_url = base_url[:-1] if base_url.endswith("/") else base_url
self.token = token
- def update(self, sensorName: str, present_date: str or None, sensorState: float, sensorUnit: str):
+ def update(self, sensorName: str, present_date: str or None, sensorState: float, sensorUnit: str, month=False):
"""
Update the sensor state
:param sensorName: 此为id,不是name
@@ -28,7 +28,10 @@ def update(self, sensorName: str, present_date: str or None, sensorState: float,
"Authorization": "Bearer " + token
}
- last_updated = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f%z")
+ if month:
+ last_updated = datetime.now().strftime("%Y-%m")
+ else:
+ last_updated = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f%z")
if present_date:
request_body = {
"state": sensorState,