This project is developed in the context ofIoT oneM2M Hackthon 2021.
We would like to show our best gratitude to the organizers of the IoT oneM2M Hackthon 2021 and Korea Electronics Technology Institute (KETI).
Thanks to the College of CS, Qilu University of Technology (Shandong Academy of Sciences) for giving us the opportunity to carry out this project.
At the same time, we would like to thank our academic advisors Zhang Li and Zhang Zhongjie, who gave us support and encouragement during the project and also provided us with great technical help.
1. Project background and Expectations1.1 Project backgroundWith the rapid development of science and technology, people bear more and more life pressure, and some people choose to keep pets.
According to the latest pet market analysis, the pet products market is expanding, and some people are also seeking more easy-to-use smart devices. So, an intelligent and convenient pet feeding device is necessary.
Thus, we developed an OM2M-based intelligent pet feeding system.
1.2 ExpectationsBefore making this project, we expect the following items:
1.2.1 Online control
When the pet owner is not at home, it is very annoying for the pet to be hungry. We hope that with the help of oneM2M, the pet owner can remotely control the feeder even if they are sitting in the office. Not only is it important to feed your pet, but it is also important to give your pet access to water. In short, it is important to be able to add food and water remotely.
1.2.2 Multiple control approaches
If the owner isn't in the office and does not have a PC nearby, it is necessary to use mobile devices for major functions.
1.2.3 Works even disconnected from WLAN
We want pets can be fed even their owners forget to care, and this requires thinking about under what circumstances the food and water need to be added automatically. This is where the sensor comes in.
1.2.4 More features
- In addition to basic functions, we also want to measure indoor temperature & humidity and make real-time data analysis, so that the owner can have a better understanding of the living conditions of the pet.
- People who use this smart feeder can set up a community where they can exchange pet-keeping experience and make friends.
We have made a video clip to give a brief introduction to our project, and the part 4 is the demonstration of our project.
3. High Level ArchitectureOur system is divided into data layer, service layer, communication layer, presentation layer, and each layer are subdivided. As you can see in the following picture.
The common services functions reside within a CSE They provide services to the AEs via the Mca reference point and to other CSEs via the Mcc reference point.
The following tools are required to run this project:
- Arduino IDE 1.8.5
- JAVA 1.8 or later
- MySQL 5.7 or later
- oneM2M 1.4.1
Download the code from the GIT
The necessary codes are saved in the git repository's master branch:
https://github.com/lxl2019519/oneM2M_QLU_1_project.git
The oneM2M-platform is already in the repository. You can open the file README.md for details.
6. Circuit diagram- Preparation
The NodeMCU development board is not a plug-and-play device, so we need to install drivers for it on the computer first before we can use it.
Here we are using a Windows PC to explain the driver installation. If you are using an Apple computer, you can also find the drivers for the NodeMCU board by using the download link below.
Windows download link:
CP210x USB 至 UART 桥 VCP 驱动器 - 芯科科技 (silabs.com)
Mac download link:
CP210x USB to UART Bridge VCP Drivers - Silicon Labs (silabs.com)
After opening the driver installation is completed, connect the ESP8266-NodeMCU development board to the computer, as shown below.
Check the NodeMCU development board connection ports
Open device Manager, the COM port number displayed after "Silicon Labs CP210x USB to UART Bridge" is the port number of NodeMCU development board. This information will be needed for subsequent setup work. Also note that the COM port number displayed on different computers may vary. Keep in mind the COM port number to which NodeMCU is connected on your computer.
Download and install Arduino IDE :
official website:Software | Arduino
To use the Arduino IDE with the NodeMCU development board, you need to first set up the Arduino IDE. Here we need to complete the setup of Arduino IDE and test the success of the setup using the built-in blink sample program of Arduino IDE.
Preparation
Before installing, please make sure you have done the following preparations.
1. the NodeMCU development board is connected to the computer using the USB cable
2. The NodeMCU driver has been successfully installed and you can already find the NodeMCU port number in the "Device Manager" of your computer.
3. The computer is connected to the Internet
4. you have installed the Arduino IDE on your computer (you can find the Arduino IDE download and installation package on the official website)
Configuring the compiler
- Open Arduino IDE Preferences
In the "Preferences" dialog of the Arduino IDE, find the "Additional Board Management URL".
Copy and paste the following URL into the "Additional Board Management URL" field.
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Development Board Manager" of the Arduino IDE
Type "esp8266" in the search field of "Development Board Manager".
This step requires your computer to download information from the Internet, so please make sure your computer is connected to the Internet. Select Install, here I have finished the installation. It will show INSTALLED.
- Find the "NodeMCU Development Board" in the Arduino IDE's development board menu
Find NodeMCU 1.0 (ESP - 12E Module) and select it
- Setting up the Arduino IDE's NodeMCU development board port
The port number is the port mentioned in the process above, click to select it.
Instance Verification
- Copy the following code into the compiler.
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
modified 8 May 2014
by Scott Fitzgerald
modified 2 Sep 2016
by Arturo Guadalupi
modified 8 Sep 2016
by Colby Newman
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
- Confirm that the LED on the NodeMCU development board starts blinking
Once the program is uploaded, if you see the LED on the NodeMCU development board start blinking it means that the driver has been successfully installed. Congratulations, you can now start writing control programs for the NodeMCU using the Arduino IDE.
By this point our initial configuration and testing is complete and we can come to our project, let's do it!
7.3 Start our projectFirst, we need to introduce the libraries we need to support our work below. The detailed library support and download links are listed below.
1.SimpleDHT :
Arduino temperature and humidity sensor for DHT11 and DHT22.
Download address :SimpleDHT - Arduino Libraries
Code example.
#include <SimpleDHT.h>
int pinDHT11 = 2;
SimpleDHT11 dht11(pinDHT11);
void setup() {
Serial.begin(115200);
}
void loop() {
// start working...
Serial.println("=================================");
Serial.println("Sample DHT11...");
// read without samples.
byte temperature = 0;
byte humidity = 0;
int err = SimpleDHTErrSuccess;
if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
Serial.print("Read DHT11 failed, err="); Serial.println(err);delay(1000);
return;
}
Serial.print("Sample OK: ");
Serial.print((int)temperature); Serial.print(" *C, ");
Serial.print((int)humidity); Serial.println(" H");
// DHT11 sampling rate is 1HZ.
delay(1500);
}
2.ESP8266WiFi :
Used to control the ESP8266 to connect to WiFi network
Download Address :ESP8266wifi Library | Martyn Currey
Code example.
#include <ESP8266WiFi.h>
const char* ssid = "yourWiFiname";
const char* password = "yourkey";
void setup() {
Serial.begin(9600);
WiFi.begin(ssid, password);
Serial.print("Connecting to ");
Serial.print(ssid); Serial.println(" ...");
int i = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(i++); Serial.print(' ');
}
Serial.println("");
Serial.println("Connection established!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
}
3.Servo :
Allows Arduino boards to control a variety of servo motors. This library can control a great number of servos. It makes careful use of timers: the library can control 12 servos using only 1 timer. On the Arduino Due you can control up to 60 servos.
Download Address : Servo - Arduino Reference
4.HX711:
Library to interface the Avia Semiconductor HX711 ADC. An Arduino library to interface the Avia Semiconductor HX711 24-Bit Analog-to-Digital Converter (ADC) for reading load cells / weight scales.
Download Address:HX711 Arduino Library - Arduino Reference
5.Timer :
Timer library for delaying function calls Simple non-blocking timer library for calling functions in / at / every specified units of time. Supports millis, micros, time rollover, and compile time configurable number of tasks.
Download Address : arduino-timer - Arduino Reference
Import these library functions that we downloaded into our compiler, as you can see in the following image.
Define the package pins for our subsequent use
Write the pinMapping.h file
#define D1 5
#define D2 4
#define D3 0
#define D4 2
#define D5 14
#define D6 12
#define D7 13
#define D8 15
#define D9 3
Well, now we can import our project code and upload it to compile.
7.4 Software implementation steps7.4.1 Springboot
At present, developers like to use springboot extensively, because it greatly optimizes the development process.
Specific summary: Springboot configuration files are greatly reduced, which is suitable for rapid development.
- Springboot bottom layer realizes version unification.
- Get started faster for all Spring developers.
- Out of the box, various default configurations are provided to simplify the project configuration.
- Embedded containers simplify web projects.
- There is no requirement for redundant code generation and xml configuration.
- Configure the Spring framework automatically as much as possible according to the project dependency.
- Provide functions that can be directly used in the production environment, such as performance indicators, application information and application health check.
7.4.2 Springboot creation method
There are two options to create a springboot project.
- Option A
Manually create a new project in idea. Select maven project.
The completed structure is shown in the figure.
Then the pom file inherits the spring-boot-starter-parent dependency interface to complete the creation.
- Option B
Shortcut to create the Springboot project.
(Recommend this way,We also use this method to deploy)
Accept the default option.Then introduce some dependencies statrter involved in project scenarios, that is, select the dependencies used in project development. At present, there is no choice here, and manual import is adopted directly in pom file. The complete project structure is shown in the figure.
The generated springboot project by default;
The main program has been generated, and we only need our own logic.
Resource folder directory structure Static :
Save all static resources; js CSS images ;
Templates: Save all template pages; (Spring Boot default jar package uses embedded Tomcat, and JSP pages are not supported by default); You can use the template engine (freemarker. thymeleaf);
application.properties: the configuration file of the Spring Boot application; You can modify some default settings.
7.4.3Analyze requirements and write code
After the previous steps, we have created a basic springboot project. Next, we begin to analyze our requirements and write code.
First of all, we have to complete the pet community function on the webpage and the function of obtaining and sending data according to OM2M protocol.
Community function of pets :We created the database PET on the database side, in which we created the log, message, notice, permission, role and user tables, as follows.
After creating the table, we use mybatis code generator to generate packages and class classes in java with one click.
Create a MybatisCodeGenerator class.
Configure database name and table name :
private static final DruidDataSource ds = new DruidDataSource();
private static final String schemaName = "test";
// Database name, required
private static final String[] table = {"book", ""};
// Required, the first is the table name, the second is the name of the entity class
private static final String modelName = "图书";
// Required
//==========================The above content is required============================
Configure database connection, user name and password required to connect to the database.
static {
// Required
ds.setUrl("jdbc:mysql://localhost:3306/" + schemaName +
"?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8");
ds.setUsername("root");
ds.setPassword("root");
}
private static final String BaseFilePath = System.getProperty("user.dir") + "/src/main/java/com/example/";
private static final String space4 = " ";
private static final String space6 = space4 + " ";
private static final String space8 = space4 + space4;
private static final String space12 = space4 + space8;
Create an entity folder, where Javabean are placed:
if (StrUtil.isBlank(table[0])) {
System.err.println("Please complete the configuration.");
return;
}
String entityName = getEntityName();
// 创建entity
createEntity(table[0], entityName);
createMapper(entityName);
createService(entityName);
createController(entityName, table[0]);
createXml(entityName);
// html
createVueHtml(entityName, table[0]);
Get database object :
static List<TableColumn> getTableColumns(String tableName) throws SQLException {
String sql = "SELECT table_name,column_name,data_type, column_comment FROM information_schema.COLUMNS WHERE table_schema = ? and table_name = ?";
List<Entity> user = Db.use(ds).query(sql, schemaName, tableName);
List<TableColumn> columnList = Lists.newArrayList();
for (Entity entity : user) {
TableColumn tableColumn = new TableColumn();
tableColumn.setTableName(entity.getStr("table_name"));
tableColumn.setColumnName(entity.getStr("column_name"));
tableColumn.setDataType(convertDataType(entity.getStr("data_type")));
tableColumn.setColumnComment(entity.getStr("column_comment"));
columnList.add(tableColumn);
}
return columnList;
}
Generate entity:
static void createEntity(String tableName, String entityName) throws SQLException {
List<TableColumn> columnList = getTableColumns(tableName);
StringBuilder entityHeadBuild = StrUtil.builder()
.append("package com.example.entity;\n\n")
.append("import lombok.Data;\n")
.append("import com.baomidou.mybatisplus.annotation.TableName;\n")
.append("import com.baomidou.mybatisplus.annotation.IdType;\n")
.append("import com.baomidou.mybatisplus.extension.activerecord.Model;\n")
.append("import com.baomidou.mybatisplus.annotation.TableId;\n\n");
StringBuilder entityBodyBuild = StrUtil.builder()
.append("@Data\n")
.append("@TableName(\"").append(tableName).append("\")\n")
.append("public class ").append(entityName).append(" extends Model<").append(entityName).append("> {\n")
.append(space4).append("/**\n")
.append(space6).append("*").append(" 主键\n")
.append(space6).append("*/\n")
.append(space4).append("@TableId(value = \"id\", type = IdType.AUTO)\n")
.append(space4).append("private Long id;\n\n");
for (TableColumn tableColumn : columnList) {
String columnName = tableColumn.getColumnName();
if (!"id".equals(columnName)) {
// 注释
if (StrUtil.isNotBlank(tableColumn.getColumnComment())) {
entityBodyBuild
.append(space4).append("/**\n")
.append(space6).append("* ").append(tableColumn.getColumnComment()).append(" \n")
.append(space6).append("*/\n");
}
entityBodyBuild.append(space4).append("private ").append(tableColumn.getDataType()).append(" ").append(StrUtil.toCamelCase(columnName)).append(";\n\n");
}
}
// 查看是否需要额外导入包
boolean dateExists = columnList.stream().anyMatch(tableColumn -> tableColumn.getDataType().equals("Date"));
if (dateExists) {
entityHeadBuild.append("import java.util.Date;\n");
}
boolean decimalExists = columnList.stream().anyMatch(tableColumn -> tableColumn.getDataType().equals("BigDecimal"));
if (decimalExists) {
entityHeadBuild.append("import java.math.BigDecimal;\n");
}
entityHeadBuild.append("\n");
entityBodyBuild.append("}");
FileUtil.writeString(entityHeadBuild.append(entityBodyBuild).toString(), BaseFilePath + "/entity/" + entityName + ".java", "UTF-8");
System.out.println(entityName + "EntityGenerate success!");
}
The generated entity class code is as above, and the rest is similar to generate mapper, generate service, generate controller, generate XML, and generate page similar.
Get entity name:
static String getEntityName() {
return StrUtil.isBlank(MybatisCodeGenerator.table[1]) ? toCamelFirstUpper(MybatisCodeGenerator.table[0]) : MybatisCodeGenerator.table[1];
}
Turn the hump and capitalize the first letter:
public static String toCamelFirstUpper(String str) {
String s = StrUtil.toCamelCase(str);
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
Capitalize the first letter, convert the data type:
public static String toFirstUpper(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
public static String convertDataType(String sqlType) {
switch (sqlType) {
case "varchar":
case "longtext":
case "text":
return "String";
case "double":
return "Double";
case "int":
return "Integer";
case "tinyint":
return "Boolean";
case "bigint":
return "Long";
case "datetime":
case "timestamp":
return "Date";
case "decimal":
return "BigDecimal";
default:
return "";
}
}
At this point, the directory structure we need to do our duty has been built.
- So far, we have completed the framework of the project directory
- The core part: get and send data from the OM2M platform
Get data from OM2M:
//Cat food storage capacity
String str =getData("http://192.168.209.14:8090/~/server/server/mydevice1/grainweight/la", "");
JSONObject object = JSONObject.parseObject(str); //Convert the result into json format
JSONObject object1= (JSONObject) object.get("m2m:cin");
ult = (String)object1.get("con");
System.out.println("ult"+ult+"acquire success。");
cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject();
The most important of these is the getData function, which is used to obtain a connection with the OM2M platform.
path refers to the path of data stored in IN-CSE on OM2M
public static String getData(String path, String data) {
String str = "";
String str1="";
try {
URL url = new URL(path);
//Open the connection with the url
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
PrintWriter out = null;
/**Set URLConnection parameters and common request attributes****start***/
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept","application/json");
conn.setRequestProperty("X-M2M-Origin", "admin:admin");
/**Set URLConnection parameters and common request attributes****end***/
conn.setDoOutput(true);
conn.setDoInput(true);
//GET and POST must be all uppercase
conn.setRequestMethod("GET");
/**GET method request*****start*/
conn.connect();
/**GET method request*****end*/
//Get the input stream corresponding to the URLConnection object
InputStream is = conn.getInputStream();
//Construct a character stream cache
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((str = br.readLine()) != null) {
//Solve the Chinese garbled problem
str = new String(str.getBytes(), "UTF-8");
str1=str1+str;
}
//Close stream
is.close();
conn.disconnect();
System.out.println("Complete end");
} catch (Exception e) {
e.printStackTrace();
}
return str1;
}
Set whether to output to httpUrlConnection and whether to read in from httpUrlConnection. In addition, these two must be set to send a post request.
The most commonly used Http requests are nothing more than get and post. Get requests can obtain static pages, or put parameters after the URL string and pass them to the servlet.
The difference between post and get is that the parameters of post are not placed in the URL string, but placed in the body of the http request.
If you just send a GET request, use the connect method to establish an actual connection with the remote resource;
if you send a POST request, you need to obtain the output stream corresponding to the URLConnection instance to send the request parameters.
Disconnect, it is best to write, disconnect is to cut off when the underlying tcp socket link is idle. Don't cut off if it is being used by other threads.
If you have fixed multi-threading, if you don't disconnect, the link will increase until you can't send and receive information. After writing disconnect, it will be normal.
- The core part: get and send data from the OM2M platform
public cn.hutool.json.JSONObject aaa(){
cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject();
String body= "{'m2m:cin': {'con': 'ServoON'}}";
String servo1 = sendPost("http://101.42.104.122:8080/server/mydevice1/servo", body);
JSONObject object = JSONObject.parseObject(servo1);
JSONObject object1= (JSONObject) object.get("m2m:cin");
String servo =(String)object1.get("con");
jsonObject.set("msg", servo);
return jsonObject;
}
What is written in servo1 is the path corresponding to the tree in OM2M, and the body is the specific information to be modified, which has been written in json format.
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// Open the connection with the URL
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setInstanceFollowRedirects(true);
// Set general request attributes
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
// conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
conn.setRequestProperty("Content-Type", "application/vnd.onem2m-res+json;ty=4;charset=utf-8");
conn.setRequestProperty("Accept","application/json");
conn.setRequestProperty("X-M2M-RI","12345");
conn.setRequestProperty("X-M2M-Origin","Cae-admin5");
conn.connect();
OutputStreamWriter outputStreamWriter =
new OutputStreamWriter(conn.getOutputStream(), "utf-8");
out = new PrintWriter(outputStreamWriter);
//Convert json format string
JSONObject jsonObject = JSONObject.parseObject(param);
out.print(jsonObject);
// flush output stream buffer
out.flush();
out.close();
//View status code
int responseCode = conn.getResponseCode();
// Define the BufferedReader input stream to read the response of the URL
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("The POST request is abnormal!" + e);
e.printStackTrace();
}
//Use finally block to close output stream and input stream
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
In the post implementation function, the connection with the URL address is opened first, and then the general request attributes are set. Only in this way can the OM2M be correctly connected, and then the obtained is converted into a json format string.
The above is the key code to realize the connection with the OM2M platform to send and obtain data.
8. Introduction of Web page- Sign in & Sign up page
- Home page
With 5 button clicks, the following 5 functions are implemented:
"REFRESH" button: To get all the data for the server:
- Get the amount of water in the sink
- Get the weight of the food in the food tank (by this reflecting the amount of food left over)
- Get the temperature and humidity in the current machine environment
"FOOD REMAINING" & "WATER STORAGE" buttons: To get one of the data in the server:
- Get the amount of food left in the food tank and the amount of water in the sink
"ADD WATER" & "ADD FOOD" buttons: To send data to the server:
- Send the relevant control commands to the oneM2M tree corresponding to the specific sensor
- Notification Center
This section consists of three drop-down menus:
- Displays the String type data taken from the tree of oneM2M and pulls this data away from the data needed.
- Displays: the amount of water in the sink, the weight of the food in the food tank (by which it reflects the amount of food remaining), the temperature and humidity in the current environment of the machine
- Water section
- Temperature & humidity section
- Food and water left over section
- User information section
Contains two items:
---The second is to log out, you can log out of the current login account to achieve the new account login
- User Management page
Query: You can search for keywords, search from the database, and display eligible content
New: You can add a new content that appears at the bottom of the entire catalog.
- Role Management Page
Query and add sections
Query: You can search for keywords, search from the database, and display eligible content
New: You can add a new content that appears at the bottom of the entire catalog.
Action: Remove or edit permissions
- Authority Management page
Action: You can delete and edit specific data
- Pet BBS Page
This page is divided into three sections Gellery, Community, and Personal information
- Masterpiece gallery
Users can upload their pets' cute photos to the BBS.
- Online message section
- User information change section
You can set up your own information
- First, let's open the Android Studio, and open our project.
- Now we can see that the Android part is divided into 8 classes, They control different functions.
- The class MyApplication is used to define various communication addresses so that we can get the data.
- And the class OneFragment is used to control add food function.
- The TwoFragment is used to control add water function.
- Finally, we can use the android virtual machine or a android phone to run the app.
- Based on the powerful support of OM2M, the owner can check the current amount of food or water left in storage or pets' bowl via web or mobile device (Android).
- If the remaining amount is too low, the owner can put food and water remotely on web or mobile devices (Android).
- The owner can also see the current indoor temperature and humidity, and when the living condition is bad, the owner can remotely control thier homes' air conditioner to maintain a suitable living environment for the pets.
- What's more, the feeding machine can show the current time and vivid pictures. The alarm LEDs will be turned on if the remaining amount of food or water in storage is too low.
- And last but not least, the web page of the feeding system has rich functions. This part will be introduced in detail in Part 4 Demonstration, including multiple real-time data analysis, online communities, where users can make comments and reply to each other. Users can also be assigned different permissions.
10.2.1 When feeder is ONLINE (The feeder is connected to WLAN)
Web:
- Add food remotely by "ADD FOOD" button;
- Add water remotel by "ADD WATER" button;
- Notification Center to view the latest data;
- Check the amount of food left in pet's bowl;
- Check the amount of water left in pet's cup;
- Picture Gallery show;
- Sign in & sign up accounts;
- Pets community (comments & replies);
- Authority management (Administrator & User);
- Pie chart of water remaining;
- Bar chart of food remaining;
- Bar chart of water remaining;
- Bar chart of daily temperature;
- Line chart of temperature change;
- Line chart of humidity change;
- Line chart of water in storage change;
Android:
- Check the amount of food left in pet's bowl;
- Check the amount of food left in storage;
- Check the amount of water left in pet's cup;
- Add food remotely;
- Add water remotely;
10.2.2 When feeder is OFFLINE (The feeder is disconnected from WLAN)
- Add food automatically when too little in food in pet's bowl and lasts for 6 hours; [Prevent pets from eating too much]
- Add water automatically when too little water in pet's bottle;
- Show color images on LCD
- Show current time on LCD;
- Water Alarm LED turns on when too little water in storage;
- Food Alarm LED turns on when too little food in storage;
- More solid shell
Prevent pets from destroying the machine;
- STM32-based switch to control food or water adding without Wi-Fi
Owners don't have to open the webpage or Android app to add food or water when they are next to the machine.
Comments