8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Inkbirdの温湿度計のデータをRaspberry Piで取得しPrometheusとGrafanaで可視化する

Last updated at Posted at 2021-05-13

はじめに

Inkbirdの温湿度計IBS-TH1やIBS-TH2は、専用のスマホアプリを使ってBluetooth経由で取得したデータを参照することができます。
スマホアプリだとグラフの読み込みに時間がかかることやアプリをインストールした端末からしかデータを参照できない不便さがあるので、PrometheusとGrafanaを使ってWebブラウザで参照できるように設定してみました。

スマホアプリだと、こんな感じ。

参考情報

複数のIBS-THシリーズからBluetooth経由でデータを取得するコードは、@c60evaporatorさんの記事 家の中のセンサデータをRaspberryPiで取得しまくり、スーパーIoTハウスを実現 をもとにしています。元記事にはない IBS-TH2やPrometheus exporterの処理を追加し、今回使用しないセンサー向けの処理は省きました。

準備するもの

センサーはIBS-TH1かIBS-TH2のいずれかがあれば今回の記事の内容を試すことができます。同じセンサーが複数個あっても設定可能です。

ゴール

スマホアプリで見ている情報を、Grafanaで見られるようにします。

3台のセンサーをそれぞれ以下の場所に設置し、データを取得しています。
IBS-TH1 : 外部プローブをワインセラー庫内に入れて温湿度を計測
IBS-TH2 (温湿度計) : ワインセラーを置いている収納スペースの温湿度を計測
IBS-TH2 (温度計のみ) : 書斎の室温を計測

grafana-20210513.png

環境構築

前提条件

Raspbian OSを使用。

/etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

Pythonのコードを実行するディレクトリは、/home/pi/raspberry-inkbird_ibsth/
(別のディレクトリにコードや設定ファイルを配置する場合は、後述のcronや設定内のパスも変更が必要です。)

最終的にはこのようなディレクトリ構成となります。
Sensorディレクトリ以下のファイルやディレクトリは、Pythonスクリプトにより自動生成されます。

$ tree /home/pi/raspberry-inkbird_ibsth/
/home/pi/raspberry-inkbird_ibsth/
├── config.ini
├── Data
│   ├── inkbird-ibs-th.prom
│   └── Sensor
│       ├── Inkbird_IBSTH1_1
│       │   └── 2021
│       │       └── Inkbird_IBSTH1_1_202105.csv
│       ├── Inkbird_IBSTH2_1
│       │   └── 2021
│       │       └── Inkbird_IBSTH2_1_202105.csv
│       └── Inkbird_IBSTH2_2
│           └── 2021
│               └── Inkbird_IBSTH2_2_202105.csv
├── DeviceList.csv
├── inkbird_ibsth1.py
├── Log
│   ├── inkbird-ibs-th1.prom
│   └── Sensor
│       ├── sensorlog_210501.log
│       ├── sensorlog_210502.log
│       └── sensorlog_210503.log
└── sensors_to_prometheus.py

Python3や必要なライブラリのインストール

$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install python3-dev python3-pip libglib2.0-dev bluez libatlas-base-dev
$ pip3 install bluepy pandas prometheus-client

crontabの有効化

Raspberry Pi 4ではcrontabがデフォルトでは有効になっていないため、設定を変更します。

/etc/rsyslog.conf
- #cron.*            /var/log/cron.log
+ cron.*             /var/log/cron.log

設定を変更後、rsyslogを再起動します。

$ sudo /etc/init.d/rsyslog restart
/etc/default/cron
- #EXTRA_OPTS=''
+ EXTRA_OPTS='-L 15'

設定を変更後、cronを再起動します。

$ sudo /etc/init.d/cron restart
$ sudo /bin/systemctl enable cron.service

Pythonスクリプトの設置

ディレクトリの作成

$ cd /home/pi
$ mkdir -p ./raspberry-inkbird_ibsth/{Data/Sensor,Log/Sensor}

設定ファイル

  • DeviceList.csv

センサーごとの情報を記載します。ここでは3台のセンサーを設定しています。

/home/pi/raspberry-inkbird_ibsth/DeviceList.csv
DeviceName,SensorType,MacAddress,Timeout,Retry,Offset_Temp,Offset_Humid,API_URL,Token
Inkbird_IBSTH1_1,Inkbird_IBSTH1,10:08:xx:xx:xx:xx,0,2,0,0,,
Inkbird_IBSTH2_1,Inkbird_IBSTH2,49:42:xx:xx:xx:xx,0,2,0,0,,
Inkbird_IBSTH2_2,Inkbird_IBSTH2,49:42:xx:xx:xx:xx,0,2,0,0,,

カラムの仕様は、家の中のセンサデータをRaspberryPiで取得しまくり、スーパーIoTハウスを実現設定ファイルの項目を参照。

DeviceName:デバイス名を管理、同種類のセンサが複数あるときの識別用
SensorType:センサの種類。この値に応じ実行するセンサデータ取得クラスを分ける
MacAddress:センサのMACアドレス
Timeout:スキャン時のタイムアウト値(ブロードキャストモードのセンサのみ、推奨値5前後)
Retry:最大再実行回数(詳細、推奨値2~3)
Offset_Temp:温度オフセット値(現状未使用)
Offset_Humid:湿度オフセット値(現状未使用)
API_URL:APIのURL(Nature Remoのみ使用)
Token:アクセストークン(Nature Remoのみ使用)

センサーのMACアドレスは、Inkbird IBS-TH1の値をRaspberryPiでロギングの解説もしくは、Inkbirdのスマホアプリから確認できます。


  • config.ini

ログやCSVの出力先を記載します。CSVデータは今回の記事内では使用しませんが、取得したデータのログとして残しています。

/home/pi/raspberry-inkbird_ibsth/config.ini
[Path]
CSVOutput  = /home/pi/raspberry-inkbird_ibsth/Data/Sensor
LogOutput  = /home/pi/raspberry-inkbird_ibsth/Log/Sensor
PromOutPut = /home/pi/raspberry-inkbird_ibsth/Data/inkbird-ibs-th.prom

CSVOutput : センサーごとに取得したデータをCSVで記録したもの
LogOutput : Pythonスクリプトの動作ログ
PromOutPut : Prometheus node exporterの出力先

Pythonスクリプト本体 

/home/pi/raspberry-inkbird_ibsth/inkbird_ibsth1.py
# coding=UTF-8

from bluepy import btle
import struct

#Inkbird IBS-TH1データ取得クラス
class GetIBSTH1Data():
    def get_ibsth1_data(self, macaddr, sensortype):
        #デバイスに接続
        peripheral = btle.Peripheral(macaddr)
        #IBS-TH2のとき
        if sensortype == 'Inkbird_IBSTH2':
            characteristic = peripheral.readCharacteristic(0x24)
            return self._decodeSensorData_th2(characteristic)
        #IBS-TH1のとき
        elif sensortype == 'Inkbird_IBSTH1':
            characteristic = peripheral.readCharacteristic(0x28)
            return self._decodeSensorData_th1(characteristic)
        else:
            return None

    #IBS-TH2
    def _decodeSensorData_th2(self, valueBinary):
        (temp, humid, unknown1, unknown2, unknown3) = struct.unpack('<hhBBB', valueBinary)
        sensorValue = {
                'SensorType': 'Inkbird_IBSTH2',
                'Temperature': float(temp) / 100,
                'Humidity': float(humid) / 100,
                'unknown1': unknown1,
                'unknown2': unknown2,
                'unknown3': unknown3,
            }
        return sensorValue

    #IBS-TH1
    def _decodeSensorData_th1(self, valueBinary):
        (temp, humid, unknown1, unknown2, unknown3) = struct.unpack('<hhBBB', valueBinary)
        sensorValue = {
                'SensorType': 'Inkbird_IBSTH1',
                'Temperature': temp / 100,
                'Humidity': humid / 100,
                'unknown1': unknown1,
                'unknown2': unknown2,
                'unknown3': unknown3,
            }
        return sensorValue
  • sensors_to_prometheus.py
/home/pi/raspberry-inkbird_ibsth/sensors_to_prometheus.py
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from bluepy import btle
from inkbird_ibsth1 import GetIBSTH1Data
from datetime import datetime, timedelta
from prometheus_client import Counter, Gauge, write_to_textfile, REGISTRY
import os
import csv
import configparser
import pandas as pd
import requests
import logging
import subprocess
import time

#グローバル変数
global masterdate

######Inkbird IBS-TH1のデータ取得######
def getdata_ibsth1(device):
    #値が得られないとき、最大device.Retry回スキャンを繰り返す
    for i in range(device.Retry):
        try:
            sensorValue = GetIBSTH1Data().get_ibsth1_data(device.MacAddress, device.SensorType)
        #エラー出たらログ出力
        except:
            logging.warning(f'retry to get data [loop{str(i)}, date{str(masterdate)}, device{device.DeviceName}]')
            sensorValue = None
            continue
        else:
            break

    if sensorValue is not None:
        #POSTするデータ
        data = {
            'DeviceName': device.DeviceName,
            'Date_Master': str(masterdate),
            'Date': str(datetime.today()),
            'Temperature': str(sensorValue['Temperature']),
            'Humidity': str(sensorValue['Humidity']),
        }
        return data
    #値取得できていなかったら、ログ出力してBluetoothアダプタ再起動
    else:
        logging.error(f'cannot get data [loop{str(device.Retry)}, date{str(masterdate)}, device{device.DeviceName}]')
        restart_hci0(device.DeviceName)
        return None


######データのCSV出力######
def output_csv(data, csvpath):
    dvname = data['DeviceName']
    monthstr = masterdate.strftime('%Y%m')
    #出力先フォルダ名
    outdir = f'{csvpath}/{dvname}/{masterdate.year}'
    #出力先フォルダが存在しないとき、新規作成
    os.makedirs(outdir, exist_ok=True)
    #出力ファイルのパス
    outpath = f'{outdir}/{dvname}_{monthstr}.csv'

    if not os.path.exists(outpath):
        with open(outpath, 'w') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writeheader()
            writer.writerow(data)
    #出力ファイル存在するとき、1行追加
    else:
        with open(outpath, 'a') as f:
            writer = csv.DictWriter(f, data.keys())
            writer.writerow(data)

######温度と湿度データを.promファイルに出力######
def output_prometheus_collector(data):
    # メトリック名を指定
    g_temp  = Gauge(data['DeviceName'] + '_temp', 'Gauge')
    g_humid = Gauge(data['DeviceName'] + '_humid','Gauge')

    while True:
        g_temp.set(data['Temperature'])
        g_humid.set(data['Humidity'])

        # promファイルに出力
        write_to_textfile(cfg['Path']['PromOutPut'], REGISTRY)
        break


######Bluetoothアダプタ再起動######
def restart_hci0(devicename):
    passwd = 'RaspberryPiパスワードを入力'
    subprocess.run(('sudo','-S','hciconfig','hci0','down'), input=passwd, check=True)
    subprocess.run(('sudo','-S','hciconfig','hci0','up'), input=passwd, check=True)
    logging.error(f'restart bluetooth adapter [date{str(masterdate)}, device{devicename}]')


######メイン######
if __name__ == '__main__':
    #開始時刻を取得
    startdate = datetime.today()
    #開始時刻を分単位で丸める
    masterdate = startdate.replace(second=0, microsecond=0)
    if startdate.second >= 30:
        masterdate += timedelta(minutes=1)

    #設定ファイルとデバイスリスト読込
    cfg = configparser.ConfigParser()
    cfg.read('./config.ini', encoding='utf-8')
    df_devicelist = pd.read_csv('./DeviceList.csv')
    #全センサ数とデータ取得成功数
    sensor_num = len(df_devicelist)
    success_num = 0

    #ログの初期化
    logname = f"/sensorlog_{str(masterdate.strftime('%y%m%d'))}.log"
    logging.basicConfig(filename=cfg['Path']['LogOutput'] + logname, level=logging.INFO)


    ######デバイスごとにデータ取得######
    for device in df_devicelist.itertuples():
        #Inkbird IBS-TH1
        if device.SensorType in ['Inkbird_IBSTH2','Inkbird_IBSTH1']:
            data = getdata_ibsth1(device)
        #上記以外
        else:
            data = None

        #データが存在するとき、CSV、Prometheusに出力
        if data is not None:
            # Inkbird
            if device.SensorType in ['Inkbird_IBSTH2','Inkbird_IBSTH1']:
                # Prometheus textfile collector出力
                output_prometheus_collector(data)

            #CSV出力
            output_csv(data, cfg['Path']['CSVOutput'])
            #成功数プラス
            success_num+=1


    #処理終了をログ出力
    logging.info(f'[masterdate{str(masterdate)} startdate{str(startdate)} enddate{str(datetime.today())} success{str(success_num)}/{str(sensor_num)}]')

crontabの設定

piユーザーのcrontabに以下の設定を追加します。
毎分スクリプトを実行し、config.iniに指定したファイルにログなどを出力します。
正常に動作しない場合、/var/log/syslogを確認します。

* * * * * cd /home/pi/raspberry-inkbird_ibsth;  /usr/bin/python3 /home/pi/raspberry-inkbird_ibsth/sensors_to_prometheus.py >/dev/null 2>&1

Prometheusのインストールと設定

PrometheusはOSのパッケージマネージャ経由でインストールします。

node_exporterのインストールと設定

Node ExporterにTextfile Collectorを設定し、指定したディレクトリにある.promファイル内の値をPrometheusが取得できるようにします。

prometheus-node-exporterをインストール。

$ sudo apt-get install prometheus-node-exporter

node_exporterを実行するprometheusユーザーを追加。

$ sudo useradd -U -s /sbin/nologin -M -d / prometheus

prometheus-node-exporterの起動を確認。

$ systemctl status prometheus-node-exporter
● prometheus-node-exporter.service - node_exporter for Prometheus
   Loaded: loaded (/etc/systemd/system/prometheus-node-exporter.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2021-04-03 22:55:06 JST; 4 weeks 2 days ago
 Main PID: 5305 (prometheus-node)
    Tasks: 16 (limit: 4915)
   CGroup: /system.slice/prometheus-node-exporter.service

systemd経由でnode_exporterを管理できるよう、/etc/systemd/system/prometheus-node-exporter.serviceとして以下の内容のファイルを作成します。ここで、prometheus-node-exporterの起動オプションとして --collector.textfile.directory の値に前述の前提条件に記載した実行ディレクトリを指定しています。

/etc/systemd/system/prometheus-node-exporter.service
[Unit]
Description=node_exporter for Prometheus

[Service]
Restart=always
User=prometheus
ExecStart=/usr/bin/prometheus-node-exporter --collector.textfile.directory /home/pi/raspberry-inkbird_ibsth/Data
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

systemdの設定を再読み込みする。

$ sudo systemctl daemon-reload

Prometheus Serverのインストールと設定

Prometheusをインストールします。

$ sudo apt-get install prometheus

node_exporter同様にsystemdでprometheusを管理できるよう/etc/systemd/system/prometheus.serviceとして以下の内容のファイルを作成します。
--storage.tsdb.retention.time=1y 取得したデータの保持期間を設定しています。デフォルトは15d(15日間)です。データ容量とディスクサイズ、必要な保持期間とのバランスで設定します。
後述の時系列データベース InfluxDB にデータを保存するため、ここでは15日に設定します。

/etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus - Monitoring system and time series database

[Service]
Restart=always
User=prometheus
ExecStart=/usr/bin/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/var/lib/prometheus/metrics --storage.tsdb.retention.time=15d
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

収集したデータを格納するディレクトリを--storage.tsdb.pathで指定しています。このディレクトリを作成します。

$ sudo mkdir -p /var/lib/prometheus
$ sudo chown prometheus:prometheus /var/lib/prometheus

systemdの設定を再読み込みする。

$ sudo systemctl daemon-reload

Prometheus Serverの設定はprometheus.ymlに定義します。ここでは、Prometheusがexporterに対しデータを取りに行く間隔scrape_intervalを1m(1分)に設定しています。

/etc/prometheus/prometheus.yml
global:
  scrape_interval:     1m
  evaluation_interval: 1m


# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093']

scrape_configs:
  - job_name: 'prometheus'

    static_configs:
      - targets: ['localhost:9090']

  - job_name: node
    static_configs:
      - targets: ['localhost:9100']

OS起動時にPrometheus Serverが自動起動するようにします。

sudo systemctl enable prometheus.service

Prometheus Serverを起動します。

sudo systemctl start prometheus.service

WebブラウザからPrometheusコンソールにアクセスする

Prometheus Serverを起動後、Webブラウザで http://(Raspberry Pi4のIPアドレス):9090/ にアクセスすると、コンソールが表示されます。

Prometheus01.png

inkbird-ibs-th.promにPrometheus exporterのデータが正しく出力されていれば、-insert metric at cursor-のプルダウンメニューにDeviceList.csvで設定したデバイス名が表示されます。

Prometheus02.png

どれかひとつを選択しExecuteをクリック->Graphタブをクリックすると、センサーから取得した値をもとにグラフが描画されます。
Prometheus03.png

Grafanaのインストールと設定

Grafanaのインストール

Grafanaは、公式サイトのInstall on Debian or Ubuntuに従ってインストールします。

$ curl https://packages.grafana.com/gpg.key | sudo apt-key add -
$ echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
$ sudo apt-get install apt-transport-https
$ sudo apt-get update
$ sudo apt-get install grafana

systemdの設定を再読み込みする。

$ sudo /bin/systemctl daemon-reload

OS起動時にGrafanaが自動起動するようにします。

$ sudo /bin/systemctl enable grafana-server

$ Grafanaを起動します。

$ sudo /bin/systemctl start grafana-server

WebブラウザからGrafanaコンソールにアクセスする

Grafanaを起動後、Webブラウザで http://(Raspberry Pi4のIPアドレス):3000/ にアクセスすると、コンソールが表示されます。
初回は、Username, Passwordともadminでログインできます。ログイン後、パスワードを変更します。

Grafana01.png

Grafanaの設定

データソースを指定

PrometheusのデータをGrafanaで読み込むためのデータソースを指定します。
左サイドバーの歯車アイコンからData Sourcesをクリックします。

Grafana02.png

Data Sourcesのタブ内にあるAdd data sourceをクリックし、表示された時系列データベース一覧からPrometheusをクリックします。

Grafana03.png

Nameに適当なデータソース名を入力します。URLは、PrometheusのWebコンソールにアクセスした際のURLを入力します。その他の項目はデフォルトのままとし、画面下部のSave & Testをクリックします。Data source is workingと表示されれば成功です。

Grafana04.png

ダッシュボードを作成

様々なグラフを管理するダッシュボードを追加します。
左サイドバーの+アイコンからDashboardをクリックします。

Grafana05.png

QueryタブのMetricsプルダウンからInkbirdを選択し、展開された一覧からパネルに表示するデータを選択します。
Grafana06.png

グラフの見た目や追加表示する項目、凡例などは右側のPanelタブ内の項目で設定可能です。
今回は、温度と湿度のデータを取得したので、グラフのY軸に設定する単位はAxesLeft YにあるUnitで設定します。

単位に温度を設定する場合。
Grafana12.png

単位に湿度を設定する場合
Grafana13.png

それぞれのグラフをダッシュボードに追加すると、以下のようになります。
Grafana14.png

グラフの設定

Panelタブ内の設定です。

Grafana07.png
Grafana08.png
Grafana09.png
Grafana10.png
Grafana11.png

InfluxDBのインストールと設定

センサーから取得したデータを長期保存するためデータをリモートストレージへ転送し、Grafanaはリモートストレージをデータストアとして使用するように設定を変更します。

InfluxDBのインストール

InfluxDBのリポジトリを登録します。

$ wget -qO- https://repos.influxdata.com/influxdb.key | sudo apt-key add -
$ echo "deb https://repos.influxdata.com/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/influxdb.list

InfluxDBをインストールします。

$ sudo apt update && sudo apt install -y influxdb

OS起動時にサービスが自動起動するように設定します。

$ sudo systemctl unmask influxdb.service
$ sudo systemctl start influxdb
$ sudo systemctl enable influxdb.service

IncludDBの設定

センサーのデータを投入するデータベースを作成します。

$ influx
Connected to http://localhost:8086 version 1.8.6
InfluxDB shell version: 1.8.6
> CREATE DATABASE prometheus

データベースが作成されたことが確認できます。

> show databases;
name: databases
name
----
_internal
prometheus

prometheus.ymlをに remote_readremote_writeを追記します。

/etc/prometheus/prometheus.yml
global:
  scrape_interval:     1m
  evaluation_interval: 1m


# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093']

scrape_configs:
  - job_name: 'prometheus'

    static_configs:
      - targets: ['localhost:9090']

  - job_name: node
    static_configs:
      - targets: ['localhost:9100']

remote_write:
  - url: "http://localhost:8086/api/v1/prom/write?db=prometheus"

remote_read:
  - url: "http://localhost:8086/api/v1/prom/read?db=prometheus"

サービスを再起動します。

$ sudo systemctl daemon-reload
$ sudo systemctl reload prometheus.service

データベースを確認

 $ influx
Connected to http://localhost:8086 version 1.8.6
InfluxDB shell version: 1.8.6
> use prometheus
Using database prometheus
> show MEASUREMENTS
name: measurements
name
----
Inkbird_IBSTH1_1_humid
Inkbird_IBSTH1_1_temp
Inkbird_IBSTH2_1_humid
Inkbird_IBSTH2_1_temp
Inkbird_IBSTH2_2_humid
Inkbird_IBSTH2_2_temp
(後略)

毎分データが登録されているので、Prometheusを再起動した数分後にはこのようなデータが確認できます。

> select * from Inkbird_IBSTH1_1_humid limit 5;
name: Inkbird_IBSTH1_1_humid
time                __name__               instance       job  value
----                --------               --------       ---  -----
1622648491459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 62.87
1622648551459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 62.68
1622648611459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 62.28
1622648671459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 61.98
1622648731459000000 Inkbird_IBSTH1_1_humid localhost:9100 node 61.58

Grafanaの設定

データソースを指定

GrafanaのデータソースにInfluxDBを追加します。

influxdb01.png

Nameに適当なデータソース名を入力します。 URLはhttp://localhost:8086を指定します。
influxdb02.png

Databaseは、先ほど作成した prometheus を指定します。 画面下部のSave & Testをクリックします。Data source is workingと表示されれば成功です。
influxdb03.png

新たにダッシュボードを作成しパネルを追加、もしくは、Prometheusをデータソースとして作成したダッシュボードのパネルを編集します。

QueryタブのデーターソースプルダウンからInfluxDBを選択し、FROMプルダウンからパネルに表示させるデータを選択します。1分毎のデータなので、GROUP BYにはtime(1m)を選択します。

influxdb04.png

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?