切换页面或锁屏时关闭串口电源
26
.metadata
@ -1,10 +1,30 @@
|
|||||||
# This file tracks properties of this Flutter project.
|
# This file tracks properties of this Flutter project.
|
||||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
#
|
#
|
||||||
# This file should be version controlled and should not be manually edited.
|
# This file should be version controlled.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: b101bfe32f634566e7cb2791a9efe19cf8828b15
|
revision: cd41fdd495f6944ecd3506c21e94c6567b073278
|
||||||
channel: beta
|
channel: unknown
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
|
|
||||||
|
# Tracks metadata for the flutter migrate command
|
||||||
|
migration:
|
||||||
|
platforms:
|
||||||
|
- platform: root
|
||||||
|
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
|
||||||
|
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
|
||||||
|
- platform: android
|
||||||
|
create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
|
||||||
|
base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278
|
||||||
|
|
||||||
|
# User provided section
|
||||||
|
|
||||||
|
# List of Local paths (relative to this file) that should be
|
||||||
|
# ignored by the migrate tool.
|
||||||
|
#
|
||||||
|
# Files that are not part of the templates will be ignored by default.
|
||||||
|
unmanaged_files:
|
||||||
|
- 'lib/main.dart'
|
||||||
|
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||||
|
@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {
|
|||||||
|
|
||||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
if (flutterRoot == null) {
|
if (flutterRoot == null) {
|
||||||
throw new Exception("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
@ -28,24 +28,19 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
|||||||
android {
|
android {
|
||||||
// compileSdkVersion flutter.compileSdkVersion
|
// compileSdkVersion flutter.compileSdkVersion
|
||||||
compileSdkVersion 32
|
compileSdkVersion 32
|
||||||
ndkVersion "23.1.7779620"
|
ndkVersion flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = '1.8'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main.java.srcDirs += 'src/main/kotlin'
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "cn.com.motse.fengshui_compass"
|
applicationId "cn.com.motse.fengshui_compass"
|
||||||
|
// You can update the following values to match your application needs.
|
||||||
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||||
|
// minSdkVersion flutter.minSdkVersion
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
@ -59,19 +54,8 @@ android {
|
|||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
|
||||||
disable 'InvalidPackage'
|
|
||||||
disable "Instantiatable"
|
|
||||||
checkReleaseBuilds false
|
|
||||||
abortOnError false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
source '../..'
|
source '../..'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="cn.com.motse.fengshui_compass">
|
package="cn.com.motse.fengshui_compass">
|
||||||
<!-- Flutter needs it to communicate with the running application
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
|
the Flutter tool needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:resource="@drawable/launch_image"
|
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -0,0 +1,142 @@
|
|||||||
|
package cn.com.motse.fengshui_compass;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* author: Blankj
|
||||||
|
* blog : http://blankj.com
|
||||||
|
* time : 2016/08/07
|
||||||
|
* desc : utils about shell
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class ComShellUtils {
|
||||||
|
public static final String TAG = "CommandExecution";
|
||||||
|
|
||||||
|
public final static String COMMAND_SU = "su";
|
||||||
|
public final static String COMMAND_SH = "sh";
|
||||||
|
public final static String COMMAND_EXIT = "exit\n";
|
||||||
|
public final static String COMMAND_LINE_END = "\n";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command执行结果
|
||||||
|
*
|
||||||
|
* @author Mountain
|
||||||
|
*/
|
||||||
|
public static class CommandResult {
|
||||||
|
public int result = -1;
|
||||||
|
public String errorMsg;
|
||||||
|
public String successMsg;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CommandResult{" +
|
||||||
|
"result=" + result +
|
||||||
|
", errorMsg='" + errorMsg + '\'' +
|
||||||
|
", successMsg='" + successMsg + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行命令—单条
|
||||||
|
*
|
||||||
|
* @param command
|
||||||
|
* @param isRoot
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static CommandResult execCommand(String command, boolean isRoot) {
|
||||||
|
String[] commands = {command};
|
||||||
|
return execCommand(commands, isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行命令-多条
|
||||||
|
*
|
||||||
|
* @param commands
|
||||||
|
* @param isRoot
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static CommandResult execCommand(String[] commands, boolean isRoot) {
|
||||||
|
CommandResult commandResult = new CommandResult();
|
||||||
|
if (commands == null || commands.length == 0) return commandResult;
|
||||||
|
Process process = null;
|
||||||
|
DataOutputStream os = null;
|
||||||
|
BufferedReader successResult = null;
|
||||||
|
BufferedReader errorResult = null;
|
||||||
|
StringBuilder successMsg = null;
|
||||||
|
StringBuilder errorMsg = null;
|
||||||
|
try {
|
||||||
|
process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
|
||||||
|
os = new DataOutputStream(process.getOutputStream());
|
||||||
|
for (String command : commands) {
|
||||||
|
if (command != null) {
|
||||||
|
os.write(command.getBytes());
|
||||||
|
os.writeBytes(COMMAND_LINE_END);
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.writeBytes(COMMAND_EXIT);
|
||||||
|
os.flush();
|
||||||
|
commandResult.result = process.waitFor();
|
||||||
|
//获取错误信息
|
||||||
|
successMsg = new StringBuilder();
|
||||||
|
errorMsg = new StringBuilder();
|
||||||
|
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||||
|
String s;
|
||||||
|
while ((s = successResult.readLine()) != null) {
|
||||||
|
successMsg.append(s);
|
||||||
|
}
|
||||||
|
while ((s = errorResult.readLine()) != null) {
|
||||||
|
errorMsg.append(s);
|
||||||
|
}
|
||||||
|
commandResult.successMsg = successMsg.toString();
|
||||||
|
commandResult.errorMsg = errorMsg.toString();
|
||||||
|
Log.i(TAG, commandResult.result + " | " + commandResult.successMsg
|
||||||
|
+ " | " + commandResult.errorMsg);
|
||||||
|
} catch (IOException e) {
|
||||||
|
String errmsg = e.getMessage();
|
||||||
|
if (errmsg != null) {
|
||||||
|
Log.e(TAG, errmsg);
|
||||||
|
} else {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
String errmsg = e.getMessage();
|
||||||
|
if (errmsg != null) {
|
||||||
|
Log.e(TAG, errmsg);
|
||||||
|
} else {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (os != null) {
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
if (successResult != null) {
|
||||||
|
successResult.close();
|
||||||
|
}
|
||||||
|
if (errorResult != null) {
|
||||||
|
errorResult.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
String errmsg = e.getMessage();
|
||||||
|
if (errmsg != null) {
|
||||||
|
Log.e(TAG, errmsg);
|
||||||
|
} else {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (process != null) {
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return commandResult;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package cn.com.motse.fengshui_compass;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import io.flutter.embedding.android.FlutterActivity;
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine;
|
||||||
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
|
public class MainActivity extends FlutterActivity {
|
||||||
|
private static final String CHANNEL = "toggle_power";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
|
||||||
|
super.configureFlutterEngine(flutterEngine);
|
||||||
|
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
|
||||||
|
.setMethodCallHandler(
|
||||||
|
(call, result) -> {
|
||||||
|
if (call.method.equals("turnOnPower")) {
|
||||||
|
String state = "1";
|
||||||
|
String ioValue = "236";
|
||||||
|
String cmdStr1 = "echo " + ioValue + " > /sys/class/gpio/export";
|
||||||
|
String cmdStr2 = "echo out > /sys/class/gpio/gpio" + ioValue + "/direction";
|
||||||
|
String cmdStr3 = "echo " + state + " > /sys/class/gpio/gpio" + ioValue + "/value";
|
||||||
|
ComShellUtils.execCommand(cmdStr1, false);
|
||||||
|
ComShellUtils.execCommand(cmdStr2, false);
|
||||||
|
ComShellUtils.execCommand(cmdStr3, false);
|
||||||
|
result.success("on");
|
||||||
|
} else if (call.method.equals("turnOffPower")) {
|
||||||
|
String state = "0";
|
||||||
|
String ioValue = "236";
|
||||||
|
String cmdStr1 = "echo " + ioValue + " > /sys/class/gpio/export";
|
||||||
|
String cmdStr2 = "echo out > /sys/class/gpio/gpio" + ioValue + "/direction";
|
||||||
|
String cmdStr3 = "echo " + state + " > /sys/class/gpio/gpio" + ioValue + "/value";
|
||||||
|
ComShellUtils.execCommand(cmdStr1, false);
|
||||||
|
ComShellUtils.execCommand(cmdStr2, false);
|
||||||
|
ComShellUtils.execCommand(cmdStr3, false);
|
||||||
|
result.success("off");
|
||||||
|
} else {
|
||||||
|
result.notImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
package cn.com.motse.fengshui_compass
|
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Modify this file to customize your launch splash screen -->
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="@color/transparent" />
|
<item android:drawable="@android:color/white" />
|
||||||
|
|
||||||
<!-- You can insert your own image assets here -->
|
<!-- You can insert your own image assets here -->
|
||||||
<item>
|
<!-- <item>
|
||||||
<bitmap
|
<bitmap
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:src="@drawable/launch_image" />
|
android:src="@mipmap/launch_image" />
|
||||||
</item>
|
</item> -->
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
Before Width: | Height: | Size: 540 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 544 B |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 721 B |
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 1.4 KiB |
@ -3,7 +3,7 @@
|
|||||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
Flutter draws its first frame -->
|
the Flutter engine draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
Flutter draws its first frame -->
|
the Flutter engine draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
@ -14,7 +14,5 @@
|
|||||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||||
<item name="android:windowBackground">?android:colorBackground</item>
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<color name="transparent">#00000000</color>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="cn.com.motse.fengshui_compass">
|
package="cn.com.motse.fengshui_compass">
|
||||||
<!-- Flutter needs it to communicate with the running application
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
|
the Flutter tool needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
@ -6,7 +6,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
|
||||||
|
@ -7,6 +7,7 @@ import 'package:fengshui_compass/components/my_icon.dart';
|
|||||||
import 'package:fengshui_compass/pages/login_page.dart';
|
import 'package:fengshui_compass/pages/login_page.dart';
|
||||||
import 'package:fengshui_compass/states/region.dart';
|
import 'package:fengshui_compass/states/region.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_serial_port_api/flutter_serial_port_api.dart';
|
import 'package:flutter_serial_port_api/flutter_serial_port_api.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@ -23,7 +24,7 @@ class CompassPage extends StatefulWidget {
|
|||||||
State<StatefulWidget> createState() => _CompassState();
|
State<StatefulWidget> createState() => _CompassState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CompassState extends State<CompassPage> {
|
class _CompassState extends State<CompassPage> with WidgetsBindingObserver {
|
||||||
// 串口相关
|
// 串口相关
|
||||||
bool isPortOpened = false;
|
bool isPortOpened = false;
|
||||||
SerialPort _serialPort;
|
SerialPort _serialPort;
|
||||||
@ -54,16 +55,53 @@ class _CompassState extends State<CompassPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
print("init");
|
||||||
|
// 添加观察者以监听生命周期事件
|
||||||
|
WidgetsBinding.instance?.addObserver(this);
|
||||||
initPort();
|
initPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
turnOffPower();
|
||||||
|
// 在小部件被销毁时移除观察者,以防止内存泄漏
|
||||||
|
WidgetsBinding.instance?.removeObserver(this);
|
||||||
|
super.dispose();
|
||||||
|
print("dispose");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
|
// 在这里处理应用程序生命周期状态变化事件
|
||||||
|
if (state == AppLifecycleState.paused) {
|
||||||
|
// 应用程序进入后台
|
||||||
|
print('App entered background');
|
||||||
|
turnOffPower();
|
||||||
|
} else if (state == AppLifecycleState.resumed) {
|
||||||
|
// 应用程序回到前台
|
||||||
|
print('App returned to foreground');
|
||||||
|
initPort();
|
||||||
|
} else if (state == AppLifecycleState.inactive) {
|
||||||
|
// 应用程序处于非活动状态(例如:锁屏、电话来电)
|
||||||
|
print('App in inactive state');
|
||||||
|
turnOffPower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> initPort() async {
|
Future<void> initPort() async {
|
||||||
|
await turnOnPower();
|
||||||
|
// todo:
|
||||||
|
setState(() {
|
||||||
|
isLock = true;
|
||||||
|
isUpClose = true;
|
||||||
|
isSideClose = true;
|
||||||
|
});
|
||||||
// 20ms接收一次串口数据,防抖,定义接收缓存
|
// 20ms接收一次串口数据,防抖,定义接收缓存
|
||||||
final debounceTransformer = StreamTransformer<Uint8List, dynamic>.fromBind(
|
final debounceTransformer = StreamTransformer<Uint8List, dynamic>.fromBind(
|
||||||
(s) => s.transform(debounceBuffer(const Duration(milliseconds: 20))));
|
(s) => s.transform(debounceBuffer(const Duration(milliseconds: 20))));
|
||||||
|
|
||||||
if (!isPortOpened) {
|
if (!isPortOpened) {
|
||||||
Device theDevice = Device("/dev/ttyS2", "/dev/ttyS2");
|
Device theDevice = Device("/dev/ttyS3", "/dev/ttyS3");
|
||||||
var serialPort = await FlutterSerialPortApi.createSerialPort(
|
var serialPort = await FlutterSerialPortApi.createSerialPort(
|
||||||
theDevice, 115200,
|
theDevice, 115200,
|
||||||
parity: 0, dataBits: 8, stopBit: 1);
|
parity: 0, dataBits: 8, stopBit: 1);
|
||||||
@ -89,6 +127,24 @@ class _CompassState extends State<CompassPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> turnOnPower() async {
|
||||||
|
const platform = MethodChannel('toggle_power');
|
||||||
|
await platform.invokeMethod("turnOnPower");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> turnOffPower() async {
|
||||||
|
const platform = MethodChannel('toggle_power');
|
||||||
|
await platform.invokeMethod("turnOffPower");
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
isLock = false;
|
||||||
|
isUpClose = false;
|
||||||
|
isSideClose = false;
|
||||||
|
isPortOpened = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> closePort() async {
|
Future<void> closePort() async {
|
||||||
bool closeResult = await _serialPort.close();
|
bool closeResult = await _serialPort.close();
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -204,24 +260,33 @@ class _CompassState extends State<CompassPage> {
|
|||||||
w_y_tmp = 0.5 - 0.07 * roll_tmp / 30.0;
|
w_y_tmp = 0.5 - 0.07 * roll_tmp / 30.0;
|
||||||
w_x_tmp = 0.5 - 0.07 * pitch_tmp / 30.0;
|
w_x_tmp = 0.5 - 0.07 * pitch_tmp / 30.0;
|
||||||
} else if (w_total > 30) {
|
} else if (w_total > 30) {
|
||||||
//todo
|
// //todo
|
||||||
w_y_tmp = 0.5 - 0.07 * w_total / 30.0;
|
// w_y_tmp = 0.5 - 0.07 * w_total / 30.0;
|
||||||
w_x_tmp = 0.5 - 0.07 * w_total / 30.0;
|
// w_x_tmp = 0.5 - 0.07 * w_total / 30.0;
|
||||||
|
var radius = sqrt(0.07 * 0.07 * 2);
|
||||||
|
//todo;
|
||||||
|
var _angle = atan2(roll_tmp, -pitch_tmp);
|
||||||
|
if (_angle < 0) {
|
||||||
|
_angle += 2 * pi;
|
||||||
|
}
|
||||||
|
w_y_tmp = 0.5 - radius * sin(_angle);
|
||||||
|
w_x_tmp = 0.5 + radius * cos(_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo 其他情况
|
// todo 其他情况
|
||||||
|
|
||||||
var meanValue;
|
var meanValue;
|
||||||
|
|
||||||
if (lista.length < 20) {
|
// if (lista.length < 20) {
|
||||||
lista.add(temp_myaw);
|
// lista.add(temp_myaw);
|
||||||
meanValue = null;
|
// meanValue = null;
|
||||||
} else {
|
// } else {
|
||||||
lista.removeAt(0);
|
// lista.removeAt(0);
|
||||||
lista.add(temp_myaw);
|
// lista.add(temp_myaw);
|
||||||
meanValue = lista.map((e) => e).reduce((a, b) => a + b) / lista.length;
|
// meanValue = lista.map((e) => e).reduce((a, b) => a + b) / lista.length;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// print("roll: $roll_tmp pitch: $pitch_tmp");
|
// print("roll: $roll_tmp pitch: $pitch_tmp");
|
||||||
// print("w_x: $w_x_tmp, w_y: $w_y_tmp");
|
// print("w_x: $w_x_tmp, w_y: $w_y_tmp");
|
||||||
@ -238,6 +303,7 @@ class _CompassState extends State<CompassPage> {
|
|||||||
// 水平仪 0.5+-0.07范围
|
// 水平仪 0.5+-0.07范围
|
||||||
// x旋转y在动 y旋转x在动 roll改变y坐标,pitch改变x坐标
|
// x旋转y在动 y旋转x在动 roll改变y坐标,pitch改变x坐标
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else if (str.contains("9E010401") &&
|
} else if (str.contains("9E010401") &&
|
||||||
(str.length >= ((str.indexOf("9E010401") + 26)))) {
|
(str.length >= ((str.indexOf("9E010401") + 26)))) {
|
||||||
var pos = str.indexOf("9E010401");
|
var pos = str.indexOf("9E010401");
|
||||||
@ -311,7 +377,8 @@ class _CompassState extends State<CompassPage> {
|
|||||||
} else if (angle > 180) {
|
} else if (angle > 180) {
|
||||||
result = angle - 180;
|
result = angle - 180;
|
||||||
} else {
|
} else {
|
||||||
result = 0.0;
|
// result = 0.0;
|
||||||
|
result = angle;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|