1
0
Fork 0
mirror of https://github.com/silenty4ng/k5web synced 2025-04-01 21:25:02 +00:00
This commit is contained in:
Silent YANG 2024-02-05 02:53:54 +08:00
parent eb4480d17f
commit e15eca6cc0

View file

@ -5,54 +5,57 @@
<a-col :span="24">
<a-card class="general-card" title="卫星写入">
<a-spin :loading="loading" style="width: 100%;" tip="正在处理 ...">
<a-form-item :label-col-style="{width: '25%'}" field="sat" label="选择卫星">
<a-form-item :label-col-style="{ width: '25%' }" field="sat" label="选择卫星">
<a-select v-model="state.sat" @change="changeSat" placeholder="选择卫星 ..." allow-search allow-clear>
<a-option v-for="item in state.satData" :key="item.name" :value="item.name">{{item.name}}</a-option>
<a-option v-for="item in state.satData" :key="item.name" :value="item.name">{{ item.name }}</a-option>
</a-select>
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="lng" label="台站经度">
<a-form-item :label-col-style="{ width: '25%' }" field="lng" label="台站经度">
<a-input-number :precision="6" v-model="state.lng" />
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="lat" label="台站纬度">
<a-form-item :label-col-style="{ width: '25%' }" field="lat" label="台站纬度">
<a-input-number :precision="6" v-model="state.lat" />
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="alt" label="台站海拔">
<a-form-item :label-col-style="{ width: '25%' }" field="alt" label="台站海拔">
<a-input-number :precision="0" v-model="state.alt" />
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" label="">
<a-form-item :label-col-style="{ width: '25%' }" label="">
<a-space>
<a-button @click="getLocation">浏览器获取经纬度</a-button>
<a-button @click="getPass">获取卫星过境时间</a-button>
</a-space>
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="pass" label="选择过境时间">
<a-form-item :label-col-style="{ width: '25%' }" field="pass" label="选择过境时间">
<a-select v-model="state.pass" allow-search allow-clear>
<a-option v-for="item in state.passOption" :key="item[0] + '|' + item[1]" :value="item[0] + '|' + item[1]">{{item[0] + " - " + item[1]}}</a-option>
<a-option v-for="item in state.passOption" :key="item[0] + '|' + item[1]"
:value="item[0] + '|' + item[1]">{{ item[0] + " - " + item[1] }}</a-option>
</a-select>
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="tx" label="上行频率">
<a-form-item :label-col-style="{ width: '25%' }" field="tx" label="上行频率">
<a-input-number :precision="5" v-model="state.tx" />
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="txTone" label="上行亚音">
<a-form-item :label-col-style="{ width: '25%' }" field="txTone" label="上行亚音">
<a-select v-model="state.txTone" allow-search allow-clear>
<a-option :value="0">关闭</a-option>
<a-option v-for="item in state.CTCSSOption" :key="item" :value="item">{{item.toFixed(1)}}</a-option>
<a-option v-for="item in state.CTCSSOption" :key="item" :value="item">{{ item.toFixed(1) }}</a-option>
</a-select>
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="rx" label="下行频率">
<a-form-item :label-col-style="{ width: '25%' }" field="rx" label="下行频率">
<a-input-number :precision="5" v-model="state.rx" />
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" field="rxTone" label="下行亚音">
<a-form-item :label-col-style="{ width: '25%' }" field="rxTone" label="下行亚音">
<a-select v-model="state.rxTone" allow-search allow-clear>
<a-option :value="0">关闭</a-option>
<a-option v-for="item in state.CTCSSOption" :key="item" :value="item">{{item.toFixed(1)}}</a-option>
<a-option v-for="item in state.CTCSSOption" :key="item" :value="item">{{ item.toFixed(1) }}</a-option>
</a-select>
</a-form-item>
<a-form-item :label-col-style="{width: '25%'}" label="">
<a-form-item :label-col-style="{ width: '25%' }" label="">
<a-button @click="writeIt">写入数据</a-button>
</a-form-item>
<a-divider />
<div id="statusArea" style="height: 20em; background-color: azure; color: silver; overflow: auto; padding: 20px" v-html="state.status"></div>
<div id="statusArea"
style="height: 20em; background-color: azure; color: silver; overflow: auto; padding: 20px"
v-html="state.status"></div>
</a-spin>
</a-card>
</a-col>
@ -63,14 +66,14 @@
<script lang="ts" setup>
import { reactive, nextTick } from 'vue';
import { useAppStore } from '@/store';
import { eeprom_write, eeprom_reboot, eeprom_init } from '@/utils/serial.js';
import { eeprom_write, eeprom_reboot, eeprom_init, hexReverseStringToUint8Array, stringToUint8Array } from '@/utils/serial.js';
import useLoading from '@/hooks/loading';
const { loading, setLoading } = useLoading(true);
const appStore = useAppStore();
const state : {
const state: {
status: string,
sat: string,
satData: any[],
@ -107,16 +110,16 @@ const state : {
})
const changeSat = async (sat: any) => {
const data = state.satData.find(e=>e.name == sat);
if(data && data.path){
const data = state.satData.find(e => e.name == sat);
if (data && data.path) {
state.status += '<br/>卫星参数:<br/>'
data.path.map((e:string)=>{
data.path.map((e: string) => {
state.status += e + '<br/>'
})
}
nextTick(()=>{
nextTick(() => {
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
if (textarea) textarea.scrollTop = textarea?.scrollHeight;
})
}
@ -125,16 +128,16 @@ const initSat = async () => {
const rst = await (await fetch('https://celestrak.org/NORAD/elements/amateur.txt')).text()
const lines = rst.split(/\r?\n/);
const sat = [];
let _sat:any = {};
for(let i = 0; i < lines.length; i++){
if(Number.isNaN(parseInt(lines[i].substring(0, 1)))){
if(_sat.name && _sat.name != ''){
let _sat: any = {};
for (let i = 0; i < lines.length; i++) {
if (Number.isNaN(parseInt(lines[i].substring(0, 1)))) {
if (_sat.name && _sat.name != '') {
sat.push(_sat)
_sat = {}
}
_sat.name = lines[i]
}else{
if(!_sat.path){_sat.path = []}
} else {
if (!_sat.path) { _sat.path = [] }
_sat.path.push(lines[i])
}
}
@ -144,11 +147,11 @@ const initSat = async () => {
initSat()
const getLocation = async () => {
setLoading(true)
navigator.geolocation.getCurrentPosition((e)=>{
if(e.coords){
navigator.geolocation.getCurrentPosition((e) => {
if (e.coords) {
state.lat = e.coords.latitude
state.lng = e.coords.longitude
if(e.coords.altitude)state.alt = e.coords.altitude
if (e.coords.altitude) state.alt = e.coords.altitude
}
});
setLoading(false)
@ -160,9 +163,9 @@ const restoreRange = async (start: any = 0, uint8Array: any) => {
for (let i = start; i < uint8Array.length + start; i += 0x80) {
await eeprom_write(appStore.connectPort, i, uint8Array.slice(i - start, i - start + 0x80), 0x80, appStore.configuration?.uart);
state.status = state.status + "写入进度:" + (((i - start) / uint8Array.length) * 100).toFixed(1) + "%<br/>";
nextTick(()=>{
nextTick(() => {
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
if (textarea) textarea.scrollTop = textarea?.scrollHeight;
})
}
state.status = state.status + "写入进度100.0%<br/>";
@ -170,7 +173,7 @@ const restoreRange = async (start: any = 0, uint8Array: any) => {
}
const getPass = async () => {
if(!state.sat){alert('请选择卫星!'); return;};
if (!state.sat) { alert('请选择卫星!'); return; };
setLoading(true)
const res = await (await fetch('https://k5.vicicode.com/api/pass', {
method: "POST",
@ -180,34 +183,41 @@ const getPass = async () => {
},
body: JSON.stringify({
sat: state.sat,
sat_line_1: state.satData.find(e=>e.name == state.sat).path[0],
sat_line_2: state.satData.find(e=>e.name == state.sat).path[1],
sat_line_1: state.satData.find(e => e.name == state.sat).path[0],
sat_line_2: state.satData.find(e => e.name == state.sat).path[1],
lat: state.lat,
lng: state.lng,
alt: state.alt
})
})).json()
const passOption = []
for(let i=0; i<res.pass_times.length; i++){
const _passOption = [res.pass_times[i], res.departure_times[i]]
passOption.push(_passOption)
for (let i = 0; i < res.pass_times.length; i++) {
try{
let _passOption = undefined
if((Date.parse(res.departure_times[i]) - Date.parse(res.pass_times[i])) > 0){
_passOption = [res.pass_times[i], res.departure_times[i]]
}else{
_passOption = [res.pass_times[i], res.departure_times[i + 1]]
}
passOption.push(_passOption)
}catch{}
}
if(passOption.length > 0){
if (passOption.length > 0) {
state.pass = passOption[0][0] + "|" + passOption[0][1]
}else{
} else {
state.pass = undefined
}
state.passOption = passOption
setLoading(false)
}
const writeIt = async() => {
if(appStore.connectState != true){alert('请先连接手台!'); return;};
const writeIt = async () => {
if (appStore.connectState != true) { alert('请先连接手台!'); return; };
// if(appStore.configuration?.sat != true){
// alert('');
// return;
// }
if(!state.pass){alert('请选择过境时间!'); return;};
if (!state.pass) { alert('请选择过境时间!'); return; };
setLoading(true)
const res = await (await fetch('https://k5.vicicode.com/api/doppler', {
method: "POST",
@ -217,8 +227,8 @@ const writeIt = async() => {
},
body: JSON.stringify({
sat: state.sat,
sat_line_1: state.satData.find(e=>e.name == state.sat).path[0],
sat_line_2: state.satData.find(e=>e.name == state.sat).path[1],
sat_line_1: state.satData.find(e => e.name == state.sat).path[0],
sat_line_2: state.satData.find(e => e.name == state.sat).path[1],
lat: state.lat,
lng: state.lng,
alt: state.alt,
@ -228,62 +238,131 @@ const writeIt = async() => {
departure_time: state.pass.split('|')[1]
})
})).json()
state.status += JSON.stringify(res.shift_array) + '<br/>'
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
const sat = state.sat
const pass = state.pass.split('|')[0]
const pass_year = pass.split('-')[0].substring(2, 4)
const pass_month = pass.split('-')[1]
const pass_day = pass.split('-')[2].split(' ')[0]
const pass_hour = pass.split(' ')[1].split(':')[0]
const pass_min = pass.split(' ')[1].split(':')[1]
const pass_sec = pass.split(' ')[1].split(':')[2]
const departure = state.pass.split('|')[1]
const departure_year = departure.split('-')[0].substring(2, 4)
const departure_month = departure.split('-')[1]
const departure_day = departure.split('-')[2].split(' ')[0]
const departure_hour = departure.split(' ')[1].split(':')[0]
const departure_min = departure.split(' ')[1].split(':')[1]
const departure_sec = departure.split(' ')[1].split(':')[2]
// console.log(sat.trim(), new Date(pass), pass_year, pass_month, pass_day, pass_hour, pass_min, pass_sec)
// console.log(sat.trim(), new Date(departure), departure_year, departure_month, departure_day, departure_hour, departure_min, departure_sec)
await eeprom_init(appStore.connectPort);
//
let payload = new Uint8Array(10)
payload.set(stringToUint8Array(sat.trim()).subarray(0, 9))
await eeprom_write(appStore.connectPort, 0x2BA0, payload, 10, appStore.configuration?.uart);
//
await eeprom_write(appStore.connectPort, 0x2BAA, hexReverseStringToUint8Array(parseInt(pass_year).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BAB, hexReverseStringToUint8Array(parseInt(pass_month).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BAC, hexReverseStringToUint8Array(parseInt(pass_day).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BAD, hexReverseStringToUint8Array(parseInt(pass_hour).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BAE, hexReverseStringToUint8Array(parseInt(pass_min).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BAF, hexReverseStringToUint8Array(parseInt(pass_sec).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BB0, hexReverseStringToUint8Array(parseInt(departure_year).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BB1, hexReverseStringToUint8Array(parseInt(departure_month).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BB2, hexReverseStringToUint8Array(parseInt(departure_day).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BB3, hexReverseStringToUint8Array(parseInt(departure_hour).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BB4, hexReverseStringToUint8Array(parseInt(departure_min).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
await eeprom_write(appStore.connectPort, 0x2BB5, hexReverseStringToUint8Array(parseInt(departure_sec).toString(16)).subarray(0, 1), 0x01, appStore.configuration?.uart);
//
payload = new Uint8Array(2)
payload.set(hexReverseStringToUint8Array(((Date.parse(departure) - Date.parse(pass)) / 1000).toString(16)).subarray(0, 0x02))
await eeprom_write(appStore.connectPort, 0x2BB6, payload, 0x02, appStore.configuration?.uart);
//
payload = new Uint8Array(2)
if(state.txTone && state.txTone > 0){
payload.set(hexReverseStringToUint8Array(state.txTone.toString(16)).subarray(0, 0x02))
}
await eeprom_write(appStore.connectPort, 0x2BB8, payload, 0x02, appStore.configuration?.uart);
payload = new Uint8Array(2)
if(state.rxTone && state.rxTone > 0){
payload.set(hexReverseStringToUint8Array(state.rxTone.toString(16)).subarray(0, 0x02))
}
await eeprom_write(appStore.connectPort, 0x2BBA, payload, 0x02, appStore.configuration?.uart);
// UNIX200011UNIX
payload = new Uint8Array(4)
payload.set(hexReverseStringToUint8Array(((Date.parse(pass) - Date.parse('2000-01-01 00:00:00')) / 1000).toString(16)).subarray(0, 0x04))
await eeprom_write(appStore.connectPort, 0x2BBC, payload, 0x04, appStore.configuration?.uart);
const shift_arr: any = []
res.shift_array.filter((num: any, index: any) => index % 2 === 0).map((e: any)=>{
const _tx = new Uint8Array(4)
const _rx = new Uint8Array(4)
_tx.set(hexReverseStringToUint8Array(parseInt(((state.tx * 1000000 + e[0]) / 10).toFixed(0)).toString(16)))
_rx.set(hexReverseStringToUint8Array(parseInt(((state.rx * 1000000 + e[1]) / 10).toFixed(0)).toString(16)))
shift_arr.push(..._tx, ..._rx)
})
payload = new Uint8Array(0x1E00)
payload.set(new Uint8Array(shift_arr).subarray(0, 0x1E00))
await restoreRange(0x1E200, payload)
setLoading(false)
}
</script>
<script lang="ts">
export default {
name: 'Chi',
};
export default {
name: 'Sat',
};
</script>
<style scoped lang="less">
.container {
padding: 0 20px 20px 20px;
:deep(.arco-list-content) {
overflow-x: hidden;
}
.container {
padding: 0 20px 20px 20px;
:deep(.arco-card-meta-title) {
font-size: 14px;
}
}
:deep(.arco-list-col) {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
:deep(.arco-list-content) {
overflow-x: hidden;
}
:deep(.arco-list-item) {
width: 33%;
}
:deep(.block-title) {
margin: 0 0 12px 0;
:deep(.arco-card-meta-title) {
font-size: 14px;
}
:deep(.list-wrap) {
// min-height: 140px;
.list-row {
align-items: stretch;
.list-col {
margin-bottom: 16px;
}
}
:deep(.arco-list-col) {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
:deep(.arco-list-item) {
width: 33%;
}
:deep(.block-title) {
margin: 0 0 12px 0;
font-size: 14px;
}
:deep(.list-wrap) {
// min-height: 140px;
.list-row {
align-items: stretch;
.list-col {
margin-bottom: 16px;
}
:deep(.arco-space) {
width: 100%;
.arco-space-item {
&:last-child {
flex: 1;
}
}
:deep(.arco-space) {
width: 100%;
.arco-space-item {
&:last-child {
flex: 1;
}
}
}
</style>
}</style>