Форум программистов, компьютерный форум, киберфорум
Программирование Android
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 18

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

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

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

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

Решил я за бабахать умные весы для пасеки!
Нужны они для отслеживания привесов отдельного, среднего по силе улья и ведения журнала привесов(сколько принесли пчёлки, с каких цветочков и где пасека находится). Для этого пчеловод ставит этот улей на весы и каждый день в определённое время проверяет изменение веса(привес, либо отвес). Пчеловод не каждый день бывает на своей пасеке, но ему хочется знать средние результаты труда его "работниц". Как это сделать? Взвешивать и отправлять данные... Можно по смс, через интернет на сервер, либо непосредственно с весов в приложение по 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
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
22.04.2021, 16:00
Ответы с готовыми решениями:

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

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

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

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

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

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

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

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

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

Если не лукавить, то и лишнего смартфона пока нет.
0
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 18
25.04.2021, 11:33  [ТС]
Подключил вывод графика
Кликните здесь для просмотра всего текста
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
Сообщений: 18
25.04.2021, 11:43  [ТС]
Пока приложение выглядит так.
0
69 / 62 / 13
Регистрация: 10.01.2012
Сообщений: 508
25.04.2021, 20:08
Чё за либа делает график, как и откуда по оси Х вставляются цифири, это int или другое?
0
1 / 1 / 0
Регистрация: 02.02.2020
Сообщений: 18
25.04.2021, 20:20  [ТС]
Графики строит - mpandroidchart.
Цифры вставляются в entries.add(new Entry(d2, Float.parseFloat(listItems.get(i).getStr ing("itog")))), где в2 это значение Х, а всё остальное Y.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.04.2021, 20:20
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru