1048 lines
36 KiB
Dart
1048 lines
36 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io' show Platform;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:workmanager/workmanager.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'dart:developer' as dev;
|
|
|
|
const _channelId = 'alert_channel';
|
|
const _channelName = 'Alerty';
|
|
const _channelDescription = 'Alerty z API (lodówka Ubibot)';
|
|
final _notifs = FlutterLocalNotificationsPlugin();
|
|
|
|
Future<void> _ensureNotificationChannel() async {
|
|
final android = _notifs.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>();
|
|
await android?.createNotificationChannel(
|
|
const AndroidNotificationChannel(
|
|
_channelId,
|
|
_channelName,
|
|
description: _channelDescription,
|
|
importance: Importance.max,
|
|
),
|
|
);
|
|
}
|
|
|
|
NotificationDetails get _alertDetails => const NotificationDetails(
|
|
android: AndroidNotificationDetails(
|
|
_channelId,
|
|
_channelName,
|
|
channelDescription: _channelDescription,
|
|
importance: Importance.max,
|
|
priority: Priority.high,
|
|
),
|
|
);
|
|
|
|
@pragma('vm:entry-point')
|
|
void callbackDispatcher() {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
Workmanager().executeTask((taskName, _inputData) async {
|
|
const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
await _notifs.initialize(
|
|
const InitializationSettings(android: initAndroid),
|
|
);
|
|
|
|
await _ensureNotificationChannel();
|
|
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final url = prefs.getString('APIURL') ?? '';
|
|
final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
|
|
|
|
final response =
|
|
await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30));
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = json.decode(response.body);
|
|
final field8 = data['channel']?['last_values'] != null
|
|
? json.decode(data['channel']['last_values'])['field8']
|
|
: null;
|
|
|
|
if (field8 != null && field8['value'] != null) {
|
|
final double temp = field8['value'].toDouble();
|
|
if (temp > threshold) {
|
|
await _notifs.show(
|
|
DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
'⚠️ ALERT',
|
|
'Temperatura wzrosła powyżej progu: $temp°C > $threshold°C',
|
|
_alertDetails,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
await _notifs.show(
|
|
DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
'Błąd API',
|
|
e.toString(),
|
|
_alertDetails,
|
|
);
|
|
}
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
Future<void> main() async {
|
|
dev.log('starting...', name: 'lodowka_ubibot');
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString(
|
|
'APIURL',
|
|
'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
|
|
);
|
|
|
|
const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
await _notifs.initialize(const InitializationSettings(android: initAndroid));
|
|
|
|
if (Platform.isAndroid) {
|
|
final android = _notifs.resolvePlatformSpecificImplementation<
|
|
AndroidFlutterLocalNotificationsPlugin>();
|
|
final granted = await android?.requestNotificationsPermission();
|
|
if (granted == null || !granted) {
|
|
print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
|
|
}
|
|
}
|
|
|
|
await _ensureNotificationChannel();
|
|
|
|
await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
|
await Workmanager().registerPeriodicTask(
|
|
'checkApiPeriodic',
|
|
'checkApi',
|
|
frequency: const Duration(minutes: 15),
|
|
existingWorkPolicy: ExistingWorkPolicy.keep,
|
|
);
|
|
|
|
runApp(const MyApp());
|
|
}
|
|
|
|
class MyApp extends StatefulWidget {
|
|
const MyApp({super.key});
|
|
|
|
@override
|
|
State<MyApp> createState() => _MyAppState();
|
|
}
|
|
|
|
class _MyAppState extends State<MyApp> {
|
|
final TextEditingController _controller = TextEditingController();
|
|
String _field8Value = '';
|
|
double _threshold = 5.0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadSettingsAndFetch();
|
|
}
|
|
|
|
Future<void> _loadSettingsAndFetch() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final url = prefs.getString('APIURL') ?? '';
|
|
_threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
|
|
|
|
_controller.text = url;
|
|
await _fetchField8(url);
|
|
}
|
|
|
|
Future<void> _saveApiUrl(String text) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString("APIURL", text);
|
|
}
|
|
|
|
Future<void> _saveThreshold() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setDouble("TEMP_THRESHOLD", _threshold);
|
|
}
|
|
|
|
Future<void> _fetchField8([String? customUrl]) async {
|
|
setState(() {
|
|
_field8Value = 'Ładowanie…';
|
|
});
|
|
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
|
|
final url = (customUrl ?? _controller.text).trim();
|
|
|
|
if (url.isEmpty) {
|
|
setState(() => _field8Value = 'Brak URL.');
|
|
return;
|
|
}
|
|
|
|
final response =
|
|
await http.get(Uri.parse(url)).timeout(const Duration(seconds: 15));
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = json.decode(response.body);
|
|
final field8 = data['channel']?['last_values'] != null
|
|
? json.decode(data['channel']['last_values'])['field8']
|
|
: null;
|
|
|
|
if (field8 != null && field8['value'] != null) {
|
|
final double temp = field8['value'].toDouble();
|
|
setState(() => _field8Value =
|
|
'Temperatura w lodówce: $temp °C');
|
|
|
|
// if (temp > threshold) {
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// '⚠️ ALERT',
|
|
// 'Temperatura wzrosła powyżej progu: $temp°C < ${threshold}°C',
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
} else {
|
|
setState(() => _field8Value = 'Brak danych field8.');
|
|
}
|
|
} else {
|
|
setState(() => _field8Value = 'Błąd: ${response.statusCode}');
|
|
}
|
|
} catch (e) {
|
|
setState(() => _field8Value = 'Wyjątek: $e');
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
title: 'API Alert App',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: ThemeData(useMaterial3: true),
|
|
home: Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('UbiBot - powiadomienia'),
|
|
centerTitle: true,
|
|
backgroundColor: Colors.blue,
|
|
),
|
|
body: SafeArea(
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: TextField(
|
|
controller: _controller,
|
|
decoration: const InputDecoration(
|
|
border: OutlineInputBorder(),
|
|
labelText: 'API URL',
|
|
),
|
|
onChanged: _saveApiUrl,
|
|
),
|
|
),
|
|
Padding(
|
|
padding:
|
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
child: Column(
|
|
children: [
|
|
const Text(
|
|
'Próg temperatury (°C)',
|
|
style: TextStyle(fontSize: 16),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
IconButton(
|
|
onPressed: () {
|
|
setState(() {
|
|
_threshold =
|
|
(_threshold - 0.1).clamp(-100.0, 100.0);
|
|
});
|
|
_saveThreshold();
|
|
},
|
|
icon: const Icon(Icons.remove),
|
|
),
|
|
Text(
|
|
_threshold.toStringAsFixed(1),
|
|
style: const TextStyle(fontSize: 20),
|
|
),
|
|
IconButton(
|
|
onPressed: () {
|
|
setState(() {
|
|
_threshold =
|
|
(_threshold + 0.1).clamp(-100.0, 100.0);
|
|
});
|
|
_saveThreshold();
|
|
},
|
|
icon: const Icon(Icons.add),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () => _fetchField8(),
|
|
child: const Text('Sprawdź teraz'),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Text(
|
|
_field8Value,
|
|
style: const TextStyle(fontSize: 20),
|
|
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
// import 'dart:convert';
|
|
// import 'dart:io' show Platform;
|
|
//
|
|
// import 'package:flutter/material.dart';
|
|
// import 'package:flutter/foundation.dart';
|
|
// import 'package:http/http.dart' as http;
|
|
// import 'package:workmanager/workmanager.dart';
|
|
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
// import 'package:shared_preferences/shared_preferences.dart';
|
|
// import 'dart:developer' as dev;
|
|
//
|
|
// const _channelId = 'alert_channel';
|
|
// const _channelName = 'Alerty';
|
|
// const _channelDescription = 'Alerty z API (lodówka Ubibot)';
|
|
// final _notifs = FlutterLocalNotificationsPlugin();
|
|
//
|
|
// Future<void> _ensureNotificationChannel() async {
|
|
// final android = _notifs.resolvePlatformSpecificImplementation<
|
|
// AndroidFlutterLocalNotificationsPlugin>();
|
|
// await android?.createNotificationChannel(
|
|
// const AndroidNotificationChannel(
|
|
// _channelId,
|
|
// _channelName,
|
|
// description: _channelDescription,
|
|
// importance: Importance.max,
|
|
// ),
|
|
// );
|
|
// }
|
|
//
|
|
// NotificationDetails get _alertDetails => const NotificationDetails(
|
|
// android: AndroidNotificationDetails(
|
|
// _channelId,
|
|
// _channelName,
|
|
// channelDescription: _channelDescription,
|
|
// importance: Importance.max,
|
|
// priority: Priority.high,
|
|
// ),
|
|
// );
|
|
//
|
|
// @pragma('vm:entry-point')
|
|
// void callbackDispatcher() {
|
|
// WidgetsFlutterBinding.ensureInitialized();
|
|
// Workmanager().executeTask((taskName, _inputData) async {
|
|
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
// await _notifs.initialize(
|
|
// const InitializationSettings(android: initAndroid),
|
|
// );
|
|
//
|
|
// await _ensureNotificationChannel();
|
|
//
|
|
// try {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final url = prefs.getString('APIURL') ?? '';
|
|
// final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
|
|
//
|
|
// final response =
|
|
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30));
|
|
//
|
|
// if (response.statusCode == 200) {
|
|
// final data = json.decode(response.body);
|
|
// final field8 = data['channel']?['last_values'] != null
|
|
// ? json.decode(data['channel']['last_values'])['field8']
|
|
// : null;
|
|
//
|
|
// if (field8 != null && field8['value'] != null) {
|
|
// final double temp = field8['value'].toDouble();
|
|
// if (temp > threshold) {
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// '⚠️ ALERT',
|
|
// 'Temperatura wzrosła powyżej progu: $temp°C > $threshold°C',
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
// }
|
|
// }
|
|
// } catch (e) {
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// 'Błąd API',
|
|
// e.toString(),
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
//
|
|
// return true;
|
|
// });
|
|
// }
|
|
//
|
|
// Future<void> main() async {
|
|
// dev.log('starting...', name: 'lodowka_ubibot');
|
|
// WidgetsFlutterBinding.ensureInitialized();
|
|
//
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// await prefs.setString(
|
|
// 'APIURL',
|
|
// 'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
|
|
// );
|
|
//
|
|
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
// await _notifs.initialize(const InitializationSettings(android: initAndroid));
|
|
//
|
|
// if (Platform.isAndroid) {
|
|
// final android = _notifs.resolvePlatformSpecificImplementation<
|
|
// AndroidFlutterLocalNotificationsPlugin>();
|
|
// final granted = await android?.requestNotificationsPermission();
|
|
// if (granted == null || !granted) {
|
|
// print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
|
|
// }
|
|
// }
|
|
//
|
|
// await _ensureNotificationChannel();
|
|
//
|
|
// await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
|
// await Workmanager().registerPeriodicTask(
|
|
// 'checkApiPeriodic',
|
|
// 'checkApi',
|
|
// frequency: const Duration(minutes: 15),
|
|
// existingWorkPolicy: ExistingWorkPolicy.keep,
|
|
// );
|
|
//
|
|
// runApp(const MyApp());
|
|
// }
|
|
//
|
|
// class MyApp extends StatefulWidget {
|
|
// const MyApp({super.key});
|
|
//
|
|
// @override
|
|
// State<MyApp> createState() => _MyAppState();
|
|
// }
|
|
//
|
|
// class _MyAppState extends State<MyApp> {
|
|
// final TextEditingController _controller = TextEditingController();
|
|
// final TextEditingController _thresholdController = TextEditingController();
|
|
// String _field8Value = '';
|
|
//
|
|
// @override
|
|
// void initState() {
|
|
// super.initState();
|
|
// _loadSettingsAndFetch();
|
|
// }
|
|
//
|
|
// Future<void> _loadSettingsAndFetch() async {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final url = prefs.getString('APIURL') ?? '';
|
|
// final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
|
|
//
|
|
// _controller.text = url;
|
|
// _thresholdController.text = threshold.toString();
|
|
//
|
|
// await _fetchField8(url);
|
|
// }
|
|
//
|
|
// Future<void> _saveApiUrl(String text) async {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// await prefs.setString("APIURL", text);
|
|
// }
|
|
//
|
|
// Future<void> _saveThreshold(String text) async {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final value = double.tryParse(text);
|
|
// if (value != null) {
|
|
// await prefs.setDouble("TEMP_THRESHOLD", value);
|
|
// }
|
|
// }
|
|
//
|
|
// Future<void> _fetchField8([String? customUrl]) async {
|
|
// setState(() {
|
|
// _field8Value = 'Ładowanie…';
|
|
// });
|
|
//
|
|
// try {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final threshold = prefs.getDouble('TEMP_THRESHOLD') ?? 5.0;
|
|
// final url = (customUrl ?? _controller.text).trim();
|
|
//
|
|
// if (url.isEmpty) {
|
|
// setState(() => _field8Value = 'Brak URL.');
|
|
// return;
|
|
// }
|
|
//
|
|
// final response =
|
|
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 15));
|
|
//
|
|
// if (response.statusCode == 200) {
|
|
// final data = json.decode(response.body);
|
|
// final field8 = data['channel']?['last_values'] != null
|
|
// ? json.decode(data['channel']['last_values'])['field8']
|
|
// : null;
|
|
//
|
|
// if (field8 != null && field8['value'] != null) {
|
|
// final double temp = field8['value'].toDouble();
|
|
// setState(() => _field8Value =
|
|
// 'Temperatura zewnętrzna (field8): $temp °C');
|
|
//
|
|
// if (temp < threshold) {
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// '⚠️ ALERT',
|
|
// 'Temperatura spadła poniżej progu: $temp°C < ${threshold}°C',
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
// } else {
|
|
// setState(() => _field8Value = 'Brak danych field8.');
|
|
// }
|
|
// } else {
|
|
// setState(() => _field8Value = 'Błąd: ${response.statusCode}');
|
|
// }
|
|
// } catch (e) {
|
|
// setState(() => _field8Value = 'Wyjątek: $e');
|
|
// }
|
|
// }
|
|
//
|
|
// @override
|
|
// void dispose() {
|
|
// _controller.dispose();
|
|
// _thresholdController.dispose();
|
|
// super.dispose();
|
|
// }
|
|
//
|
|
// @override
|
|
// Widget build(BuildContext context) {
|
|
// return MaterialApp(
|
|
// title: 'API Alert App',
|
|
// debugShowCheckedModeBanner: false,
|
|
// theme: ThemeData(useMaterial3: true),
|
|
// home: Scaffold(
|
|
// body: SafeArea(
|
|
// child: SingleChildScrollView(
|
|
// child: Column(
|
|
// children: [
|
|
// const Padding(
|
|
// padding: EdgeInsets.all(16.0),
|
|
// child: Text('Aplikacja nasłuchuje alertów…'),
|
|
// ),
|
|
// Padding(
|
|
// padding: const EdgeInsets.all(16.0),
|
|
// child: TextField(
|
|
// controller: _controller,
|
|
// decoration: const InputDecoration(
|
|
// border: OutlineInputBorder(),
|
|
// labelText: 'API URL',
|
|
// ),
|
|
// onChanged: _saveApiUrl,
|
|
// ),
|
|
// ),
|
|
// Padding(
|
|
// padding:
|
|
// const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
// child: TextField(
|
|
// controller: _thresholdController,
|
|
// decoration: const InputDecoration(
|
|
// labelText: 'Próg temperatury (°C)',
|
|
// border: OutlineInputBorder(),
|
|
// ),
|
|
// keyboardType:
|
|
// const TextInputType.numberWithOptions(decimal: true),
|
|
// onChanged: _saveThreshold,
|
|
// ),
|
|
// ),
|
|
// ElevatedButton(
|
|
// onPressed: () => _fetchField8(),
|
|
// child: const Text('Sprawdź teraz'),
|
|
// ),
|
|
// Padding(
|
|
// padding: const EdgeInsets.all(16.0),
|
|
// child: Text(
|
|
// _field8Value,
|
|
// style: const TextStyle(fontSize: 16),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
// import 'dart:convert';
|
|
// import 'dart:io' show Platform;
|
|
//
|
|
// import 'package:flutter/material.dart';
|
|
// import 'package:flutter/foundation.dart';
|
|
// import 'package:http/http.dart' as http;
|
|
// import 'package:workmanager/workmanager.dart';
|
|
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
// import 'package:shared_preferences/shared_preferences.dart';
|
|
// import 'dart:developer' as dev;
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // Stałe / współdzielone
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// const _channelId = 'alert_channel';
|
|
// const _channelName = 'Alerty';
|
|
// const _channelDescription = 'Alerty z API (lodówka Ubibot)';
|
|
// final _notifs = FlutterLocalNotificationsPlugin();
|
|
//
|
|
// Future<void> _ensureNotificationChannel() async {
|
|
// final android = _notifs.resolvePlatformSpecificImplementation<
|
|
// AndroidFlutterLocalNotificationsPlugin>();
|
|
// await android?.createNotificationChannel(
|
|
// const AndroidNotificationChannel(
|
|
// _channelId,
|
|
// _channelName,
|
|
// description: _channelDescription,
|
|
// importance: Importance.max,
|
|
// ),
|
|
// );
|
|
// }
|
|
//
|
|
// NotificationDetails get _alertDetails => const NotificationDetails(
|
|
// android: AndroidNotificationDetails(
|
|
// _channelId,
|
|
// _channelName,
|
|
// channelDescription: _channelDescription,
|
|
// importance: Importance.max,
|
|
// priority: Priority.high,
|
|
// ),
|
|
// );
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // CALLBACK (WorkManager)
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// @pragma('vm:entry-point')
|
|
// void callbackDispatcher() {
|
|
// WidgetsFlutterBinding.ensureInitialized();
|
|
// Workmanager().executeTask((taskName, _inputData) async {
|
|
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
// await _notifs.initialize(
|
|
// const InitializationSettings(android: initAndroid),
|
|
// );
|
|
//
|
|
// await _ensureNotificationChannel();
|
|
//
|
|
// try {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final url = prefs.getString('APIURL') ?? '';
|
|
// final response =
|
|
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 30));
|
|
//
|
|
// if (response.statusCode == 200) {
|
|
// final data = json.decode(response.body) as Map<String, dynamic>;
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// '⚠️ ALERT',
|
|
// 'Urządzenie zgłosiło alarm! $data)',
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
// } catch (e) {
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// 'Błąd API',
|
|
// e.toString(),
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
//
|
|
// return true;
|
|
// });
|
|
// }
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // MAIN
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// Future<void> main() async {
|
|
// dev.log('starting...', name: 'lodowka_ubibot');
|
|
// WidgetsFlutterBinding.ensureInitialized();
|
|
//
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// await prefs.setString(
|
|
// 'APIURL',
|
|
// 'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
|
|
// );
|
|
//
|
|
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
// await _notifs.initialize(const InitializationSettings(android: initAndroid));
|
|
//
|
|
// if (Platform.isAndroid) {
|
|
// final android = _notifs.resolvePlatformSpecificImplementation<
|
|
// AndroidFlutterLocalNotificationsPlugin>();
|
|
// final granted = await android?.requestNotificationsPermission();
|
|
// if (granted == null || !granted) {
|
|
// print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
|
|
// }
|
|
// }
|
|
//
|
|
// await _ensureNotificationChannel();
|
|
//
|
|
// await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
|
// await Workmanager().registerPeriodicTask(
|
|
// 'checkApiPeriodic',
|
|
// 'checkApi',
|
|
// frequency: const Duration(minutes: 15),
|
|
// existingWorkPolicy: ExistingWorkPolicy.keep,
|
|
// );
|
|
//
|
|
// runApp(const MyApp());
|
|
// }
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // UI (Stateful Widget)
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// class MyApp extends StatefulWidget {
|
|
// const MyApp({super.key});
|
|
//
|
|
// @override
|
|
// State<MyApp> createState() => _MyAppState();
|
|
// }
|
|
//
|
|
// class _MyAppState extends State<MyApp> {
|
|
// final TextEditingController _controller = TextEditingController();
|
|
// String _field8Value = '';
|
|
//
|
|
// @override
|
|
// void initState() {
|
|
// super.initState();
|
|
// _loadApiUrlAndFetch();
|
|
// }
|
|
//
|
|
// Future<void> _loadApiUrlAndFetch() async {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final url = prefs.getString('APIURL') ?? '';
|
|
// _controller.text = url;
|
|
// await _fetchField8(url);
|
|
// }
|
|
//
|
|
// Future<void> _saveApiUrl(String text) async {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// await prefs.setString("APIURL", text);
|
|
// }
|
|
//
|
|
// Future<void> _fetchField8([String? customUrl]) async {
|
|
// setState(() {
|
|
// _field8Value = 'Ładowanie…';
|
|
// });
|
|
//
|
|
// try {
|
|
// final url = (customUrl ?? _controller.text).trim();
|
|
// if (url.isEmpty) {
|
|
// setState(() => _field8Value = 'Brak URL.');
|
|
// return;
|
|
// }
|
|
//
|
|
// final response =
|
|
// await http.get(Uri.parse(url)).timeout(const Duration(seconds: 15));
|
|
//
|
|
// if (response.statusCode == 200) {
|
|
// final data = json.decode(response.body);
|
|
// final field8 = data['channel']?['last_values'] != null
|
|
// ? json.decode(data['channel']['last_values'])['field8']
|
|
// : null;
|
|
//
|
|
// if (field8 != null && field8['value'] != null) {
|
|
// setState(() => _field8Value =
|
|
// 'Temperatura zewnętrzna (field8): ${field8['value']} °C');
|
|
// } else {
|
|
// setState(() => _field8Value = 'Brak danych field8.');
|
|
// }
|
|
// } else {
|
|
// setState(() => _field8Value = 'Błąd: ${response.statusCode}');
|
|
// }
|
|
// } catch (e) {
|
|
// setState(() => _field8Value = 'Wyjątek: $e');
|
|
// }
|
|
// }
|
|
//
|
|
// @override
|
|
// void dispose() {
|
|
// _controller.dispose();
|
|
// super.dispose();
|
|
// }
|
|
//
|
|
// @override
|
|
// Widget build(BuildContext context) {
|
|
// return MaterialApp(
|
|
// title: 'API Alert App',
|
|
// theme: ThemeData(useMaterial3: true),
|
|
// home: Scaffold(
|
|
// body: SafeArea(
|
|
// child: SingleChildScrollView(
|
|
// child: Column(
|
|
// children: [
|
|
// const Padding(
|
|
// padding: EdgeInsets.all(16.0),
|
|
// child: Text('Aplikacja nasłuchuje alertów…'),
|
|
// ),
|
|
// Padding(
|
|
// padding: const EdgeInsets.all(16.0),
|
|
// child: TextField(
|
|
// controller: _controller,
|
|
// decoration: const InputDecoration(
|
|
// border: OutlineInputBorder(),
|
|
// labelText: 'API URL',
|
|
// ),
|
|
// onChanged: _saveApiUrl,
|
|
// ),
|
|
// ),
|
|
// ElevatedButton(
|
|
// onPressed: () => _fetchField8(),
|
|
// child: const Text('Sprawdź teraz'),
|
|
// ),
|
|
// Padding(
|
|
// padding: const EdgeInsets.all(16.0),
|
|
// child: Text(
|
|
// _field8Value,
|
|
// style: const TextStyle(fontSize: 16),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
// import 'dart:convert';
|
|
// import 'dart:io' show Platform;
|
|
//
|
|
// import 'package:flutter/material.dart';
|
|
// import 'package:flutter/foundation.dart';
|
|
// import 'package:http/http.dart' as http;
|
|
// import 'package:workmanager/workmanager.dart';
|
|
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
// import 'package:shared_preferences/shared_preferences.dart';
|
|
// import 'dart:developer' as dev;
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // Stałe / współdzielone
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// const _channelId = 'alert_channel';
|
|
// const _channelName = 'Alerty';
|
|
// const _channelDescription = 'Alerty z API (lodówka Ubibot)';
|
|
// final _notifs = FlutterLocalNotificationsPlugin();
|
|
//
|
|
// Future<void> _ensureNotificationChannel() async {
|
|
// final android = _notifs
|
|
// .resolvePlatformSpecificImplementation<
|
|
// AndroidFlutterLocalNotificationsPlugin>();
|
|
// await android?.createNotificationChannel(
|
|
// const AndroidNotificationChannel(
|
|
// _channelId,
|
|
// _channelName,
|
|
// description: _channelDescription,
|
|
// importance: Importance.max,
|
|
// ),
|
|
// );
|
|
// }
|
|
//
|
|
// NotificationDetails get _alertDetails => const NotificationDetails(
|
|
// android: AndroidNotificationDetails(
|
|
// _channelId,
|
|
// _channelName,
|
|
// channelDescription: _channelDescription,
|
|
// importance: Importance.max,
|
|
// priority: Priority.high,
|
|
// ),
|
|
// );
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // CALLBACK (WorkManager)
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// @pragma('vm:entry-point')
|
|
// void callbackDispatcher() {
|
|
// print('lodowka_ubibot: ensureInitialized()...');
|
|
// WidgetsFlutterBinding.ensureInitialized();
|
|
// print('lodowka_ubibot: Workmanager().executeTask...');
|
|
// Workmanager().executeTask((taskName, _inputData) async {
|
|
// print('lodowka_ubibot: initAndroid = AndroidInitializationSettings...');
|
|
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
// print('lodowka_ubibot: _notifs.initialize...');
|
|
// await _notifs.initialize(
|
|
// const InitializationSettings(android: initAndroid),
|
|
// );
|
|
//
|
|
// print('lodowka_ubibot: _ensureNotificationChannel()...');
|
|
// await _ensureNotificationChannel();
|
|
//
|
|
// try {
|
|
// print('lodowka_ubibot: SharedPreferences.getInstance()...');
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// print('lodowka_ubibot: prefs.getString...');
|
|
// final url = prefs.getString('APIURL') ?? '';
|
|
//
|
|
// print('lodowka_ubibot: final response = await http...');
|
|
// final response = await http
|
|
// .get(Uri.parse(url))
|
|
// .timeout(const Duration(seconds: 30));
|
|
//
|
|
// print('lodowka_ubibot: response.statusCode == 200...');
|
|
// if (response.statusCode == 200) {
|
|
// final data = json.decode(response.body) as Map<String, dynamic>;
|
|
// print('lodowka_ubibot: _notifs.show...');
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// '⚠️ ALERT',
|
|
// 'Urządzenie zgłosiło alarm! $data)',
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
// } catch (e) {
|
|
// print('lodowka_ubibot: error: $e...');
|
|
// await _notifs.show(
|
|
// DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
// 'Błąd API',
|
|
// e.toString(),
|
|
// _alertDetails,
|
|
// );
|
|
// }
|
|
//
|
|
// return true;
|
|
// });
|
|
// }
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // MAIN
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// Future<void> main() async {
|
|
// dev.log('starting...', name: 'lodowka_ubibot');
|
|
// WidgetsFlutterBinding.ensureInitialized();
|
|
//
|
|
// print('lodowka_ubibot: SharedPreferences.getInstance()...');
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// print('lodowka_ubibot: prefs.setString...');
|
|
// await prefs.setString(
|
|
// 'APIURL',
|
|
// 'https://webapi.ubibot.com/channels/107563?api_key=58045f90a943499e83ad6e945c7719e8',
|
|
// );
|
|
//
|
|
// print('lodowka_ubibot: AndroidInitializationSettings...');
|
|
// const initAndroid = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
// print('lodowka_ubibot: _notifs.initialize...');
|
|
// await _notifs.initialize(const InitializationSettings(android: initAndroid));
|
|
//
|
|
// if (Platform.isAndroid) {
|
|
// final android = _notifs
|
|
// .resolvePlatformSpecificImplementation<
|
|
// AndroidFlutterLocalNotificationsPlugin>();
|
|
// final granted = await android?.requestNotificationsPermission();
|
|
//
|
|
// if (granted == null || !granted) {
|
|
// print('⚠️ Użytkownik odmówił POST_NOTIFICATIONS.');
|
|
// }
|
|
// }
|
|
//
|
|
// print('lodowka_ubibot: _ensureNotificationChannel()...');
|
|
// await _ensureNotificationChannel();
|
|
//
|
|
// print('lodowka_ubibot: Workmanager().initialize...');
|
|
// await Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
|
//
|
|
// print('lodowka_ubibot: Workmanager().registerPeriodicTask...');
|
|
// await Workmanager().registerPeriodicTask(
|
|
// 'checkApiPeriodic',
|
|
// 'checkApi',
|
|
// frequency: const Duration(minutes: 15),
|
|
// existingWorkPolicy: ExistingWorkPolicy.keep,
|
|
// );
|
|
//
|
|
// print('lodowka_ubibot: runApp...');
|
|
// runApp(const MyApp());
|
|
// }
|
|
//
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// // UI (Stateful Widget)
|
|
// // ─────────────────────────────────────────────────────────────
|
|
// class MyApp extends StatefulWidget {
|
|
// const MyApp({super.key});
|
|
//
|
|
// @override
|
|
// State<MyApp> createState() => _MyAppState();
|
|
// }
|
|
//
|
|
// class _MyAppState extends State<MyApp> {
|
|
// final TextEditingController _controller = TextEditingController();
|
|
//
|
|
// @override
|
|
// void initState() {
|
|
// super.initState();
|
|
// _loadApiUrl();
|
|
// }
|
|
//
|
|
// Future<void> _loadApiUrl() async {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// final url = prefs.getString('APIURL') ?? '';
|
|
// setState(() {
|
|
// _controller.text = url;
|
|
// });
|
|
// }
|
|
//
|
|
// Future<void> _saveApiUrl(String text) async {
|
|
// final prefs = await SharedPreferences.getInstance();
|
|
// await prefs.setString("APIURL", text);
|
|
// }
|
|
//
|
|
// @override
|
|
// void dispose() {
|
|
// _controller.dispose();
|
|
// super.dispose();
|
|
// }
|
|
//
|
|
// @override
|
|
// Widget build(BuildContext context) {
|
|
// return MaterialApp(
|
|
// title: 'API Alert App',
|
|
// theme: ThemeData(useMaterial3: true),
|
|
// home: Scaffold(
|
|
// body: SafeArea(
|
|
// child: Column(
|
|
// children: [
|
|
// const Padding(
|
|
// padding: EdgeInsets.all(16.0),
|
|
// child: Text('Aplikacja nasłuchuje alertów…'),
|
|
// ),
|
|
// Padding(
|
|
// padding: const EdgeInsets.all(16.0),
|
|
// child: TextField(
|
|
// controller: _controller,
|
|
// decoration: const InputDecoration(
|
|
// border: OutlineInputBorder(),
|
|
// labelText: 'API URL',
|
|
// ),
|
|
// onChanged: _saveApiUrl,
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// );
|
|
// }
|
|
// }
|