Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions lib/units/ios-device/plugins/touch/esp32-movement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export const SINGLE_STEP_SIZE = 1
export const BIG_STEP_SIZE = 4
export const HUGE_STEP_SIZE = 8
export const POSITION_TOLERANCE = 1

export function getStep(diff) {
const distance = Math.abs(diff)
let magnitude = SINGLE_STEP_SIZE
if (distance >= BIG_STEP_SIZE) {
magnitude = BIG_STEP_SIZE
}
if (distance >= HUGE_STEP_SIZE) {
magnitude = HUGE_STEP_SIZE
}

return Math.sign(diff) * magnitude
}

export function getDirection(axis, step) {
const directions = {
x: {positive: ['R', 'r', 'k'], negative: ['L', 'l', 'g']},
y: {positive: ['D', 'd', 'h'], negative: ['U', 'u', 'j']}
}
const magnitude = Math.abs(step)
let index = 0
if (magnitude === BIG_STEP_SIZE) {
index = 1
}
if (magnitude === HUGE_STEP_SIZE) {
index = 2
}

return (step > 0 ? directions[axis].positive : directions[axis].negative)[index]
}
75 changes: 24 additions & 51 deletions lib/units/ios-device/plugins/touch/esp32touch.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {SerialPort} from 'serialport'
import Logger from '../../../../util/logger.js'
import {promisify} from 'node:util'
import _ from 'lodash'
import EventEmitter from 'node:events'
import {getDirection, getStep, SINGLE_STEP_SIZE, BIG_STEP_SIZE, HUGE_STEP_SIZE, POSITION_TOLERANCE} from './esp32-movement.js'


const log = Logger.createLogger('esp32touch')
Expand Down Expand Up @@ -47,9 +46,10 @@ function throttle(func, ms) {
*/
export class Esp32Touch extends EventEmitter {
static MAX_BLE_NAME_LENGTH = 22 // Match the safe limit for advertising
static SINGLE_STEP_SIZE = 13 / 3 // The amount of pixels a single step does.
static BIG_STEP_SIZE = 70 / 3 // The amount of pixels a big step does.
static HUGE_STEP_SIZE = 178 / 3 // The amount of pixels a huge step does
static SINGLE_STEP_SIZE = SINGLE_STEP_SIZE
static BIG_STEP_SIZE = BIG_STEP_SIZE
static HUGE_STEP_SIZE = HUGE_STEP_SIZE
static POSITION_TOLERANCE = POSITION_TOLERANCE

static async listPorts() {
return (await SerialPort.list()).filter((dev) => dev.manufacturer === 'Espressif')
Expand Down Expand Up @@ -167,7 +167,7 @@ export class Esp32Touch extends EventEmitter {
}
reset() {
this.bufferCommand('0')
this.curposX = 14 * Esp32Touch.SINGLE_STEP_SIZE
this.curposX = Esp32Touch.SINGLE_STEP_SIZE * 14
this.curposY = 0
}

Expand All @@ -186,56 +186,29 @@ export class Esp32Touch extends EventEmitter {
return
}

if(this.targetPosX === null || this.targetPoxY === null) {
if (this.targetPosX === null || this.targetPosY === null) {
return
}
const targetStepsX = Math.round(this.targetPosX * this.width)
const targetStepsY = Math.round(this.targetPoxY * this.height)
const diffX = targetStepsX - this.curposX // Positive -> left, negative - right
const diffY = targetStepsY - this.curposY // Positive -> up, negative - down
/** @type {[string, number, number][]} */
let commands = []
if(diffX > Esp32Touch.HUGE_STEP_SIZE * 1.5) {
commands.push(['k', Esp32Touch.HUGE_STEP_SIZE, 0])
}
if(diffX < -Esp32Touch.HUGE_STEP_SIZE * 1.5) {
commands.push(['g', -Esp32Touch.HUGE_STEP_SIZE, 0])
}
if(diffY > Esp32Touch.HUGE_STEP_SIZE * 1.5) {
commands.push(['h', 0, Esp32Touch.HUGE_STEP_SIZE])
const targetStepsY = Math.round(this.targetPosY * this.height)
const diffX = targetStepsX - this.curposX // Positive -> right, negative -> left
const diffY = targetStepsY - this.curposY // Positive -> down, negative -> up

if (Math.abs(diffX) <= Esp32Touch.POSITION_TOLERANCE && Math.abs(diffY) <= Esp32Touch.POSITION_TOLERANCE) {
return
}
if(diffY < -Esp32Touch.HUGE_STEP_SIZE * 1.5) {
commands.push(['j', 0, -Esp32Touch.HUGE_STEP_SIZE])

const moveX = Math.abs(diffX) >= Math.abs(diffY)
const step = getStep(moveX ? diffX : diffY)
// Move the axis with the larger remaining error first. Randomly
// choosing an axis makes the estimated position unstable.
let dir, addX, addY
if (moveX) {
[dir, addX, addY] = [getDirection('x', step), step, 0]
}
if (commands.length === 0) {
if(diffX > Esp32Touch.BIG_STEP_SIZE * 1.5) {
commands.push(['r', Esp32Touch.BIG_STEP_SIZE, 0])
}
if(diffX < -Esp32Touch.BIG_STEP_SIZE * 1.5) {
commands.push(['l', -Esp32Touch.BIG_STEP_SIZE, 0])
}
if(diffY > Esp32Touch.BIG_STEP_SIZE * 1.5) {
commands.push(['d', 0, Esp32Touch.BIG_STEP_SIZE])
}
if(diffY < -Esp32Touch.BIG_STEP_SIZE * 1.5) {
commands.push(['u', 0, -Esp32Touch.BIG_STEP_SIZE])
}
if(commands.length === 0) {
if(diffX > Esp32Touch.SINGLE_STEP_SIZE) {
commands.push(['R', Esp32Touch.SINGLE_STEP_SIZE, 0])
}
if(diffX < -Esp32Touch.SINGLE_STEP_SIZE) {
commands.push(['L', -Esp32Touch.SINGLE_STEP_SIZE, 0])
}
if(diffY > Esp32Touch.SINGLE_STEP_SIZE) {
commands.push(['D', 0, Esp32Touch.SINGLE_STEP_SIZE])
}
if(diffY < -Esp32Touch.SINGLE_STEP_SIZE) {
commands.push(['U', 0, -Esp32Touch.SINGLE_STEP_SIZE])
}
}
else {
[dir, addX, addY] = [getDirection('y', step), 0, step]
}
const [dir, addX, addY] = _.sample(commands) ?? ['', 0, 0]
if (dir) {
this.bufferCommand(dir)
this.curposX += addX
Expand All @@ -253,7 +226,7 @@ export class Esp32Touch extends EventEmitter {
move(targetX, targetY) {
this.startWorking()
this.targetPosX = targetX
this.targetPoxY = targetY
this.targetPosY = targetY
}

/**
Expand Down
29 changes: 29 additions & 0 deletions test/unit/units/ios-device/plugins/touch/esp32-movement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {describe, expect, it} from 'vitest'
import {getDirection, getStep} from '../../../../../../lib/units/ios-device/plugins/touch/esp32-movement.js'

describe('ESP32 movement commands', () => {
it('selects a firmware-supported step based on the remaining distance', () => {
expect(getStep(100)).toBe(8)
expect(getStep(-8)).toBe(-8)
expect(getStep(7)).toBe(4)
expect(getStep(-2)).toBe(-1)
expect(getStep(0)).toBe(0)
})

it.each([
['x', 1, 'R'],
['x', 4, 'r'],
['x', 8, 'k'],
['x', -1, 'L'],
['x', -4, 'l'],
['x', -8, 'g'],
['y', 1, 'D'],
['y', 4, 'd'],
['y', 8, 'h'],
['y', -1, 'U'],
['y', -4, 'u'],
['y', -8, 'j'],
] as const)('maps axis %s step %i to firmware command %s', (axis, step, command) => {
expect(getDirection(axis, step)).toBe(command)
})
})