1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 16
1

Приложение для весов (android приложение + связь с сервером (php & MySQL) + связь с весами + общая синхронизация данных)

22.04.2021, 16:00. Показов 1170. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем здравия братья и сестры.

Описательная часть.

Решил я за бабахать умные весы для пасеки!
Нужны они для отслеживания привесов отдельного, среднего по силе улья и ведения журнала привесов(сколько принесли пчёлки, с каких цветочков и где пасека находится). Для этого пчеловод ставит этот улей на весы и каждый день в определённое время проверяет изменение веса(привес, либо отвес). Пчеловод не каждый день бывает на своей пасеке, но ему хочется знать средние результаты труда его "работниц". Как это сделать? Взвешивать и отправлять данные... Можно по смс, через интернет на сервер, либо непосредственно с весов в приложение по Wi-fi/блютуз, когда пчеловод рядом с весами.
Проблема состоит в следующем. Пасеки не всегда находятся на одном месте(кочуют аки табор по просторам родины матушки) и на одном точкЕ(ударение на е, месте где находится пасека) есть связь ,а на другом её может не быть(это печально).

Представим нашего современного пчеловода с этими умными весами.
В один из дней он находится далеко от своей пасеки и приходит время взвешивания. Он открывает приложение на телефоне и видит вес, а также динамику изменения веса на диаграмме.
Другая ситуация. На точке нет связи. Увы пчеловод не сможет получить новые данные в приложение(пока нет идей как это победить). При следующем посещении пасеки, весы отдают результаты взвешиваний в приложение. Строится график и пчеловод снова доволен. При подключении телефона к интернету приложение отсылает данные, полученные от весов, на сервер.
И конечно к этим весам можно добавить кучу разных датчиков. (для измерения температуры, продолжительности дня, освещённости, влажности, шума, датчик движения, GPS/ГЛОНАСС и многие другие. Но это уже другая история.)

"Железная" часть.

-Весы M-ER 335ACL до 300кг. Площадка 45см*60см с аккумулятором на 3,7в и обещанным временем работы 50 дней "беспробудного" взвешивания.(2000р)
Кликните здесь для просмотра всего текста

-Плата TTGO T-Call V1.3 ESP32(~1000р)
Кликните здесь для просмотра всего текста

К этой плате:
-HX711 датчик взвешивания(~70руб)
Кликните здесь для просмотра всего текста

-B64 Micro SD плата кард-ридер(~30руб)
Кликните здесь для просмотра всего текста

-GSM-антенна для SIM800L(~70руб)
Кликните здесь для просмотра всего текста

-модуль в реальном времени DS-1302(~90руб)
Кликните здесь для просмотра всего текста

(Все кроме весов куплено в Китае, весы куплены на Авито)

Ещё нужна будет симка и флешка и батарейка таблетка.

Программно-логическая часть.

Сервер.

Создать на сервере базу данных + скрипт для обработки данных(вхоящих и исходящих)

- База состоит из трёх таблиц
* weighing_scales (id_weighing_scales, result_scale, date_scale, id_place, id_flowers)
* flowers (id_flowers, name_flowers, point)
* place (id_place, name_place, point)
point - столбец с отметкой строки по умолчанию (1-0)

- Сервер получает данные от весов $_GET['scales']-вес, $_GET['date']-дата и время взвешивания.
- Сервер обрабатывает данные и записывает в таблицу weighing_scales + берёт из двух таблиц id, отмеченные в столбце point 1

- Сервер получает запрос от приложения GET['date']-максимальная дата взвешивания хранящаяся в приложении, GET['place']-максимальный id id_place из таблицы place и GET['flowers']-максимальный id_flowers из таблицы flowers
- Сервер проверяет дату и id в соответствующих таблицах. Если такие строки имеются в таблицах и они последние добавленные, о всё ок. Если строк больше чем присланные id и дата, то недостающие строки отсылаются приложению. Если таких строк нет в таблицах, то отсылается в ответе id последней строки.

Приложение

Создать приложение, которое выводит данные из своей базы, строит график, синхронизирует данные с сервером, получает данные от весов если нет связи

- База приложения аналогична базе сервера.
- По нажатию на кнопку приложение отправляет на сервер дату и последние id из своей базы на сервер. Если сервер присылает id недостающих таблиц, то приложение формирует следующий запрос к серверу с недостающими данными. Если сервер присылает данные, то приложение их обрабатывает и добавляет в свою базу.

- Приложение принимает данные с весов, обрабатывает их и добавляет в свою базу.
- Из данных в базе приложения строится график.

Весы

Создать прошивку для платы и подружить плату с панелью управления весов.

- Подружить все компоненты весов (плата ttgo, антенна(это самое простое), модуль весов, модуль карты памяти, модуль времени, матричная клавиатура панели весов, плату сегментных индикаторов весов на базе микросхемы TM1640)

Задачи прошивки

- В определённое время(вот для чего модуль времени) получает данные от тензодатчика весов и проводить из калибровку.
- Записывает данные на флешку.
- Если есть связь, отправляет данные на сервер.
- Когда нажимают на кнопку панели весов, показывают текущий вес, отклонение веса от предыдущего взвешивания.
- Когда соединяются с приложением. Отправляют данные.
- Уходит в режим ожидания/спящий

Результаты проделанной работы.
+С сервером я разобрался.
+-Приложение с синхронизацией с сервером написал(пока без графиков и синхронизации с весами жду когда придёт из Китая)
-Весы стоят отмытые и полуразобранные. Ждут своего часа.

Хотелось бы услышать конструктивную критику, как логики проекта, так и кода.
Да, да. Я буду сюда выкладывать свой г. код.

Ещё раз жду конструктивной критики и помощи.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2021, 16:00
Ответы с готовыми решениями:

Android и приложение для ПК: удаленная связь
Здравствуйте. У меня такой вопрос. Нужно разрабатывать такой программа. Будет группа программ для...

Связь Unity3D + Arduino под android приложение
Доброго времени суток. Возникла проблема: Нужно управлять модулями Arduino с приложения под...

Выбор решения для проекта! Приложение для Windows + приложение для Android или Web приложение?
Здравствуйте! Один мой знакомый, владелец мебельной фирмы, обратился ко мне с серьезным...

связь php веб сервером Nginx
Доброго времени суток. Знатоки подскажите пожалуйста или даже разъясните один момент который сам...

8
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 16
22.04.2021, 17:54  [ТС] 2
Основные файлы моего приложения.
MainActivity.java
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
package com.example.database;
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;
 
import androidx.appcompat.app.AppCompatActivity;
 
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
 
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
 
import java.util.ArrayList;
 
public class MainActivity extends AppCompatActivity {
 
    ListView listView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        setContentView(R.layout.activity_main);
        listView = findViewById(R.id.listView);
        View InternetButton = findViewById(R.id.button1);
        InternetButton.setOnClickListener(v -> {
            //сделать ее не доступной
            if (!isOnline()) {
                Toast.makeText(getApplicationContext(),
                        "Нет соединениея с интернетом!", Toast.LENGTH_LONG).show();
 
            } else {
                Toast.makeText(getApplicationContext(),
                        "Соединение с интернетом установлено!", Toast.LENGTH_LONG).show();
                syncDb();
 
 
            }
 
        });
        View ScaleButton = findViewById(R.id.button2);
        ScaleButton.setOnClickListener(v -> {
            //сделать ее не доступной
            if (!isBluetooth()) {
                Toast.makeText(getApplicationContext(),
                        "Нет соединениея с блютуз!", Toast.LENGTH_LONG).show();
 
            } else {
                Toast.makeText(getApplicationContext(),
                        "Соединение с блютуз установлено!", Toast.LENGTH_LONG).show();
            }
 
        });
 
        loadJSONFromDB();
 
    }
 
    private void loadJSONFromDB() {
        SQLiteDatabase myDB =
                openOrCreateDatabase("my.db", MODE_PRIVATE, null);
        //ищем прогресс бар и делаем его видимым
        final ProgressBar progressBar = findViewById(R.id.progressBar);
        progressBar.setVisibility(ListView.VISIBLE);
        String select = Controller.all_scale(myDB);
 
        progressBar.setVisibility(View.INVISIBLE);
        try {
            JSONObject object = new JSONObject(select);
            JSONArray jsonArray = object.getJSONArray("data");
 
            ArrayList<JSONObject> listItems = getArrayListFromJSONArray(jsonArray);
            ListAdapter adapter = new ListViewAdapter(getApplicationContext(), R.layout.row, R.id.textViewResult, listItems);
            listView.setAdapter(adapter);
 
        } catch (JSONException e) {
            e.printStackTrace();
        }
 
        Toast.makeText(getApplicationContext(),
                "Данные из базы телефона загружены", Toast.LENGTH_LONG).show();
 
    }
 
 
    private ArrayList<JSONObject> getArrayListFromJSONArray(JSONArray jsonArray) {
        ArrayList<JSONObject> aList = new ArrayList<>();
        try {
            if (jsonArray != null) {
                for (int i = 0; i < jsonArray.length(); i++) {
                    aList.add(jsonArray.getJSONObject(i));
                }
            }
        } catch (JSONException js) {
            js.printStackTrace();
        }
        return aList;
    }
 
 
    private void syncDb() {
        SQLiteDatabase myDB =
                openOrCreateDatabase("my.db", MODE_PRIVATE, null);
        final ProgressBar progressBar = findViewById(R.id.progressBar);
        progressBar.setVisibility(ListView.VISIBLE);
        String select = Controller.syncDb(myDB);
 
        final String JSON_URL = "http://кислицин.рф/get_scale_sync";// UTF-8
 
        StringRequest stringRequest = new StringRequest(Request.Method.GET, JSON_URL + select,
                response -> {
                    progressBar.setVisibility(View.INVISIBLE);
                    try {
                        JSONObject object = new JSONObject(Controller.EncodingToUTF8(response));
 
                        if (object.has("data")) {
                            JSONArray jsonArray = object.getJSONArray("data");
                            ArrayList<JSONObject> listItems = getArrayListFromJSONArray(jsonArray);
 
                            int dateScaleSync = listItems.get(0).getInt("date");
                            int flowersScaleSync = listItems.get(0).getInt("flowers");
                            int placeScaleSync = listItems.get(0).getInt("place");
                            Context context = getApplicationContext();
                            if (object.has("sync")) {
                                //парсим данные с сервера и добавляем в базу приложения
                                JSONArray jsonArraySync = object.getJSONArray("sync");
                                ArrayList<JSONObject> listItemsSync = getArrayListFromJSONArray(jsonArraySync);
                                // String.valueOf(listItemsSync.get(0).getJSONObject("date"));
                                Controller.syncDbFromServer(myDB, context, dateScaleSync, flowersScaleSync, placeScaleSync, listItemsSync);
                            }
                            //берём данные из базы приложения и отправляем на сервер
                            if (dateScaleSync < 0 || flowersScaleSync < 0 || placeScaleSync < 0) {
                                syncDbToServer(Controller.syncDbToServer(myDB, context, dateScaleSync, flowersScaleSync, placeScaleSync));
                            }
                            Toast.makeText(getApplicationContext(),
                                    "Синхронизация завершена", Toast.LENGTH_LONG).show();
                            loadJSONFromDB();
                        } else {
                            Toast.makeText(getApplicationContext(),
                                    "Приложение синхронизировано", Toast.LENGTH_LONG).show();
                        }
 
 
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                },
                error -> Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show());
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
 
 
    }
 
    private void syncDbToServer(String addData) {
        
 
        final String JSON_URL = "http://кислицин.рф/scale_sync_add_data?data=";// UTF-8
 
        StringRequest stringRequest = new StringRequest(Request.Method.GET, JSON_URL + addData,
                response -> {
                    try {
                        JSONObject object = new JSONObject(Controller.EncodingToUTF8(response));
 
                        if (object.has("update_ok")) {
                            Toast.makeText(getApplicationContext(),
                                    "Приложение синхронизировано", Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(getApplicationContext(),
                                    "Ошибка синхронизации", Toast.LENGTH_LONG).show();
                        }
 
 
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                },
                error -> Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show());
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
 
    }
 
 
    protected boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getActiveNetworkInfo() != null;
    }
 
    protected boolean isBluetooth() {
 
        return true;
 
    }
 
 
}

Controller.java
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package com.example.database;
 
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.renderscript.Sampler;
import android.widget.Toast;
 
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
 
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
 
 
public class Controller {
 
    public static String getSyncData(SQLiteDatabase myDB, int dateScaleSync, String nameTable, String id) {
        Cursor myCursor = (Cursor) Model.getSyncData(myDB, dateScaleSync, nameTable, id);
        String result_text = dumpCursorToString(myCursor);
 
        return "\"" + nameTable + "\":[" + result_text + "]";
 
    }
 
    public static String all_scale(SQLiteDatabase myBd) {
 
        Cursor myCursor = (Cursor) Model.all_scale(myBd);
 
        StringBuilder result_text = new StringBuilder(new StringBuilder());
        int i = 0;
        if (myCursor.getCount() > 0) {
            myCursor.moveToFirst();
            float itog = 0;
            float itog_scale = 0;
            do {
                if (itog != 0) {
                    itog_scale = myCursor.getFloat(myCursor.getColumnIndex("result_scale")) - itog;
                }
                float floatNumber = BigDecimal.valueOf(itog_scale).setScale(2, BigDecimal.ROUND_HALF_DOWN).floatValue();
                String dateScales = myCursor.getString(myCursor.getColumnIndex("date"));
 
                result_text.insert(0, "{\"itog\":"
                        + floatNumber + ",\"result_scale\":"
                        + myCursor.getString(myCursor.getColumnIndex("result_scale"))
                        + ",\"date\":\"" + dateScales
                        + "\",\"name_flowers\":\""
                        + myCursor.getString(myCursor.getColumnIndex("name_flowers"))
                        + "\",\"place_name\":\""
                        + myCursor.getString(myCursor.getColumnIndex("place_name"))
                        + "\"},");
                itog = myCursor.getFloat(myCursor.getColumnIndex("result_scale"));
 
                i++;
            } while (myCursor.moveToNext());
            myCursor.close();
        }
        return "{\"data\":[" + result_text + "]}";
    }
 
    public static String syncDb(SQLiteDatabase myBd) {
        Cursor myCursor = (Cursor) Model.syncDb(myBd);
        if (myCursor.getCount() > 0) {
            myCursor.moveToFirst();
            String dateScale = myCursor.getString(myCursor.getColumnIndex("date"));
            String flowersScale = myCursor.getString(myCursor.getColumnIndex("flowers"));
            String placeScale = myCursor.getString(myCursor.getColumnIndex("place"));
 
            return "?date=" + dateScale + "&flowers=" + flowersScale + "&place=" + placeScale;
        } else {
            return "0";
        }
 
    }
 
    //сборщик недостающих данных для сервера
    static String syncDbToServer(SQLiteDatabase myDB, Context context, int dateScaleSync, int flowersScaleSync, int placeScaleSync) {
 
 
        //выбираем данные с базы приложения и отправляем на сервер
        StringBuilder ScalesSyncToServer = new StringBuilder();
 
        if (dateScaleSync < 0) {
            Toast.makeText(context, "Таблица взвешиваний на сервере меньше чем в приложении", Toast.LENGTH_LONG).show();
            ScalesSyncToServer.append(Controller.getSyncData(myDB, dateScaleSync, "weighing_scales", "id_weighing_scales"));
 
        }
        if (flowersScaleSync < 0) {
            Toast.makeText(context, "Таблица медоносов на сервере меньше чем в приложении", Toast.LENGTH_LONG).show();
 
 
            ScalesSyncToServer.append(Controller.comma(ScalesSyncToServer.length() > 0) +
                    Controller.getSyncData(myDB, flowersScaleSync, "flowers", "id_flowers"));
 
        }
        if (placeScaleSync < 0) {
            Toast.makeText(context, "Таблица локаций на сервере меньше чем в приложении", Toast.LENGTH_LONG).show();
            ScalesSyncToServer.append(Controller.comma(ScalesSyncToServer.length() > 0) +
                    Controller.getSyncData(myDB, placeScaleSync, "place", "id_place"));
        }
 
 
        return addTag(ScalesSyncToServer, "sync");
 
    }
 
    static void syncDbFromServer(SQLiteDatabase myDB, Context context, int dateScaleSync, int flowersScaleSync, int placeScaleSync, ArrayList<JSONObject> listItemsSync) throws JSONException {
 
        if (dateScaleSync > 0) {
            Toast.makeText(context, "Таблица взвешиваний на сервере больше чем в приложении", Toast.LENGTH_LONG).show();
            EncodingJSONToSqlInsert(myDB, listItemsSync, "weighing_scales");
        }
        if (flowersScaleSync > 0) {
            Toast.makeText(context, "Таблица медоносов на сервере больше чем в приложении", Toast.LENGTH_LONG).show();
            EncodingJSONToSqlInsert(myDB,  listItemsSync, "flowers");
        }
        if (placeScaleSync > 0) {
            Toast.makeText(context, "Таблица локаций на сервере больше чем в приложении", Toast.LENGTH_LONG).show();
            EncodingJSONToSqlInsert(myDB, listItemsSync,  "place");
        }
 
 
    }
 
    public static void EncodingJSONToSqlInsert(SQLiteDatabase myDB, ArrayList<JSONObject> listItemsSync, String tableName) throws JSONException {
        JSONArray weighing_scales = listItemsSync.get(0).getJSONArray(tableName);
        int count = weighing_scales.length();
        JSONArray keys = null;
 
        for (int i = 0; i < count; i++) {
            int m = 1;
            JSONObject valueString = (JSONObject) weighing_scales.get(i);
            int s = valueString.length();
            keys = valueString.names();
            ContentValues newValues = new ContentValues();
            for (int j = 0; j < s; j++) {
                assert keys != null;
                String key = keys.getString(j);
                newValues.put(key, valueString.getString(key));
            }
            Model.insertSyncData(myDB, tableName, newValues);
        }
    }
 
    public static String EncodingToUTF8(String response) {
        byte[] code = response.getBytes(StandardCharsets.ISO_8859_1);
        response = new String(code, StandardCharsets.UTF_8);
        return response;
    }
 
    public static void dumpCursor(Cursor cursor, StringBuilder sb) {
 
        if (cursor != null) {
            int startPos = cursor.getPosition();
 
            cursor.moveToPosition(-1);
            while (cursor.moveToNext()) {
                dumpCurrentRow(cursor, sb);
            }
            cursor.moveToPosition(startPos);
        }
 
    }
 
    public static String dumpCursorToString(Cursor cursor) {
        StringBuilder sb = new StringBuilder();
        dumpCursor(cursor, sb);
        return sb.toString();
    }
 
    public static void dumpCurrentRow(Cursor cursor, StringBuilder sb) {
        String[] cols = cursor.getColumnNames();
        sb.append("{");
        int length = cols.length;
        for (int i = 0; i < length; i++) {
            String z = comma(i != length - 1);
            String value;
            try {
                value = cursor.getString(i);
            } catch (SQLiteException e) {
                value = "";
            }
            sb.append('"').append(cols[i]).append("\":\"").append(value).append('"').append(z);
        }
        sb.append("}");
    }
 
    //запятая в строке
    public static String comma(boolean b) {
        String z = "";
        if (b) {
            z = ",";
        }
        return z;
    }
 
    //обёртка
    public static String addTag(StringBuilder text, String tag) {
        return "{\"" + tag + "\":{" + text + "}}";
    }
}

Model.java
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.example.database;
 
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
 
import org.jetbrains.annotations.NotNull;
 
import java.util.ArrayList;
 
 
public class Model {
 
 
    public static Object all_scale(SQLiteDatabase myBd) {
        Cursor myCursor =
                myBd.rawQuery("SELECT weighing_scales.result_scale, strftime('%d.%m\n%Y',weighing_scales.date_scale) AS date, flowers.name_flowers, place.place_name\n" +
                        "FROM weighing_scales\n" +
                        "JOIN flowers ON flowers.id_flowers = weighing_scales.id_flowers\n" +
                        "JOIN place ON place.id_place = weighing_scales.id_place\n" +
                        //"WHERE weighing_scales.result_scale>=130 \n"+
                        "ORDER BY weighing_scales.date_scale", null);
 
        return myCursor;
    }
 
    public static Object syncDb(SQLiteDatabase myBd) {
        Cursor myCursor =
                myBd.rawQuery("select(SELECT MAX(weighing_scales.date_scale) FROM weighing_scales) AS date, (SELECT MAX(flowers.id_flowers) FROM flowers) AS flowers, (SELECT MAX(place.id_place) FROM place) AS place", null);
 
        return myCursor;
    }
 
    public static Object getSyncData(SQLiteDatabase myBd, int idScaleSync, String nameTable, String nameId) {
 
 
        String sql = "SELECT * FROM " + nameTable + " WHERE " + nameId + ">" + (idScaleSync * -1);
        Cursor myCursor = myBd.rawQuery(sql, null);
 
        return myCursor;
    }
    public static void  insertSyncData(SQLiteDatabase myBd,String tableName, ContentValues newValues) {
// Вставьте строку в вашу базу данных.
        myBd.insert(tableName, null, newValues);
 
    }
}

ListViewAdapter.java
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.example.database;
 
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
 
import org.json.JSONException;
import org.json.JSONObject;
 
import java.util.ArrayList;
 
public class ListViewAdapter  extends ArrayAdapter<JSONObject> {
    int listLayout;
    ArrayList<JSONObject> usersList;
    Context context;
 
    public ListViewAdapter(Context context, int listLayout , int field, ArrayList<JSONObject> usersList) {
        super(context, listLayout, field, usersList);
        this.context = context;
        this.listLayout=listLayout;
        this.usersList = usersList;
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View listViewItem = inflater.inflate(listLayout, null, false);
        TextView date = listViewItem.findViewById(R.id.textViewDate);
        TextView result = listViewItem.findViewById(R.id.textViewResult);
        TextView flowers = listViewItem.findViewById(R.id.textViewFlowers);
        TextView itog = listViewItem.findViewById(R.id.textViewItog);
 
        try{
            date.setText(usersList.get(position).getString("date"));
            result.setText(usersList.get(position).getString("result_scale"));
            flowers.setText(usersList.get(position).getString("name_flowers"));
            itog.setText(usersList.get(position).getString("itog"));
        }catch (JSONException je){
            je.printStackTrace();
        }
        return listViewItem;
    }
 
 
}

activity_main.xml
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
 
    <LinearLayout
        android:id="@+id/btnLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center">
 
 
 
        <Button
            android:id="@+id/button1"
            android:layout_width="170dp"
            android:layout_height="wrap_content"
            android:layout_margin="2dp"
            android:text="Интернет" />
 
        <Button
            android:id="@+id/button2"
            android:layout_width="170dp"
            android:layout_height="wrap_content"
            android:layout_margin="2dp"
            android:text="Весы" />
 
 
    </LinearLayout>
 
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btnLayout"
        android:paddingTop="20dp">
 
 
    </ListView>
 
    <ProgressBar
        android:visibility="gone"
        android:id="@+id/progressBar"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
 
</RelativeLayout>

row.xml
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp">
 
    <TextView
        android:id="@+id/textViewDate"
        android:layout_width="58dp"
        android:layout_height="wrap_content"
        android:text="date"
        android:textAlignment="center"
        android:textSize="18sp" />
 
    <TextView
        android:id="@+id/textViewItog"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:text="itog"
        android:textAlignment="center"
 
        android:textSize="18sp"
        android:textStyle="bold" />
 
 
    <TextView
        android:id="@+id/textViewResult"
        android:layout_width="95dp"
        android:layout_height="wrap_content"
        android:text="result"
        android:textAlignment="center"
 
        android:textSize="18sp"
        android:textStyle="bold" />
 
    <TextView
        android:id="@+id/textViewFlowers"
        android:layout_width="130dp"
        android:layout_height="wrap_content"
        android:text="flowers"
        android:textAlignment="textStart"
        android:textSize="18sp"
        android:textStyle="italic" />
 
</LinearLayout>

AndroidManifest.xml
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.database">
 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.DataBase">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
 
            </intent-filter>
        </activity>
    </application>
 
</manifest>

Всё приложение dataBase.rar
0
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 16
22.04.2021, 18:17  [ТС] 3
И вот с этим ↑ у меня не всё ладно. С одной стороны приложение синхронизируется с сервером, но уж как-то криво сам код выглядит.
0
69 / 62 / 13
Регистрация: 10.01.2012
Сообщений: 508
22.04.2021, 23:29 4
Значит так:
Мой бы путь был таков:
В качестве накопителя инфы я бы сделал Андроид (самый голимый смартфон - згрузки то нет серьезной) и на него по воздуху скидывал бы данные от датчиков и весов (WiFi, блютуз, веревка - что есть под рукой). Такой можно тупо скотчем на ближайшее дерево повесить или куда спрятать.
Естественно БД будет sqlite.

Между личным смартфоном и голимым должен быть брокер - это уже на реальном серваке с ip адресом.
Что должен делать брокер - тупо пересылать запрос от личного к голимому, и получать от него ответ в виде файла содержащего последниие изменения в БД на голимом.

Ну типа того "Хочу обновления БД датчиков температур (всех или конкретного), сейчас у меня БД под номером 4503".
Голимый смартфон смотрит номер БД и:
Если совпадает с той что он последний раз отсылал, дает ответ - У тебя свежак и ракрывает связь.
Если номер меньше , то отсылает БД брокеру, подписав новыи номером, тот пересылает на личный смартфон. Голимый фиксит у себя кличку получателя и нимер последней отправки.

Если инета нет, то при появлении на пасике можно как поюзать голимый, так и слить с него БД но воздуху.

То есть, нарисовать некое API для беседы двух смартфонов. Команды и запросы можно будет добавлять в меру необходимости.
И не обязательно писать две разные приложухи - можно в одной через настройки указать кто Мастер, на кого он сливает.

Еще было бы неплохо и очень дешево :
Датчик -> raspberry
raspberry <-------->broker<-------->APP (flutter)
0
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 16
23.04.2021, 08:02  [ТС] 5
Со смартфоном Вы очень хорошо придумали. Внешнее хранение данных в скрытом месте. Это поможет в случае злонамеренных действий. Например. Слать туда фото-видео с WiFi дверного глазка. Видеонаблюдение и фиксация нежелательных личностей в отсутствии собственника. Даже если будет найдена камера, данные будут на телефоне в укромном месте.
Однако, дополнительное устройство, в отсутствии электричества - это дополнительная проблема. В весах стоит не плохой аккумулятор, его должно хватить на весь сезон. Работа весов от 1 до 10 максимум взвешиваний в сутки и 1 отправка в заданный период времени.
Плата TTGO T-Call V1.3 ESP32 + модули - это почти телефон и по моей задумке он всё делает сам обрабатывает полученные данные от датчиков(может в том числе получать смс с командами), пишет в файлик и высылает его при надобности.

Если не лукавить, то и лишнего смартфона пока нет.
0
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 16
25.04.2021, 11:33  [ТС] 6
Подключил вывод графика
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<Entry> entries = new ArrayList<Entry>();
            LineChart chart = (LineChart) findViewById(R.id.chart);
          
            int i = (jsonArray.length())-2;
            for (JSONObject data : listItems) {
                String[] d1 =listItems.get(i).getString("date").split("\\.");
                int d2 = Integer.parseInt(d1[0]);
                entries.add(new Entry(d2, Float.parseFloat(listItems.get(i).getString("itog"))));
                i--;
            }
            LineDataSet dataSet = new LineDataSet(entries, listItems.get(0).getString("name_flowers"));
            LineData lineData = new LineData(dataSet);
            chart.setData(lineData);
            chart.invalidate();


Но столкнулся с проблемой вывода дат в ось Х. Сейчас выводит 1 2 3 и тд. Хотелось бы дату взвешивания 12.04 хотя бы день и месяц. listItems.get(i).getString("date") здесь находится дата в формате день-месяц год. В принципе формат даты можно будет изменить на любой другой.
0
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 16
25.04.2021, 11:43  [ТС] 7
Пока приложение выглядит так.
Приложение для весов (android приложение + связь с сервером (php & MySQL) + связь с весами + общая синхронизация данных)
0
69 / 62 / 13
Регистрация: 10.01.2012
Сообщений: 508
25.04.2021, 20:08 8
Чё за либа делает график, как и откуда по оси Х вставляются цифири, это int или другое?
0
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 16
25.04.2021, 20:20  [ТС] 9
Графики строит - mpandroidchart.
Цифры вставляются в entries.add(new Entry(d2, Float.parseFloat(listItems.get(i).getString("itog")))), где в2 это значение Х, а всё остальное Y.
0
25.04.2021, 20:20
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.04.2021, 20:20
Помогаю со студенческими работами здесь

Связь нескольких приложение
Доброго времени суток, у меня имеется сайт, написанный на mvc, нужно написать приложение, которое...

PHP работа с файлами & связь с JS
Всем привет! Такая задача: есть у меня файл &quot;C:/files/textW.txt&quot; и файл &quot;C:/files/textR.txt&quot;. Еще...

Связь: ПК - Сервер - Мобильное приложение
Здравствуйте! Изучая java-у решил параллельно с книжками по базовым понятиям, почитать про сетевое...

Андроид и Пк приложение. Удаленный связь
Здравствуйте. У меня такой вопрос. Нужно разрабатывать такой программа. Будет группа программ для...

Связь php и mysql
Есть запрос mysql_query(&quot;UPDATE `$t_name` SET `Visits`=Visits+1 ,`Last`=CURRENT_DATE() WHERE...

Подружить клиентское приложение (на Android) с сервером (на Windows)
Пишу прогу, суть заключается в том, что клиентское приложение отсылает серверу текст, тот...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru