This document is written for using the web_pen_sdk
for NeoSmartPen.
# web_pen_sdk setting
$ npm install web_pen_sdk
$ yarn add web_pen_sdk
scanPen, connectDevice, serviceBinding_16, serviceBinding_128, characteristicBinding, disconnect, dotCallback, handleDot, messageCallback, handleMessage, ncodeToScreen, ncodeToScreen_smartPlate, isSamePage
This logic scans devices for Bluetooth pen connection.
/** This function scans the device for a Bluetooth pen connection. */
scanPen = async () => { ... }
// Usage with React hook
const scanPen = () => {
PenHelper.scanPen();
};
<Button onClick={scanPen}></Button>
Attempts to establish a connection with the actual Bluetooth device.
connectDevice = async (device: any) => { ... }
Binds Bluetooth services to 16-bit/128-bit UUIDs.
serviceBinding_16 = async (service: any, device: any) => { ... }
serviceBinding_128 = async (service: any, device: any) => { ... }
Sets up the PenController to handle pen events that occur after the Bluetooth pen device is connected. All pen events, including information about the connected pen and dot processing, are handled through PenController. This penController is stored in PenHelper.pens[].
characteristicBinding = (read: any, write: any, device: any) => { ... }
// PenHelper.ts
this.pens = [penController, penController, ...];
// Refer to penController usage scene 2-1
Disconnects the Bluetooth device connection.
disconnect = (penController: any) => { ... }
// Usage with React hook
const disconnectPen = () => {
PenHelper.disconnect(controller);
}
Handles events from the Bluetooth pen.
handleMessage = (controller: any, type: any, args: any) => { ... }
Type (Hex) | Title | Description | |
---|---|---|---|
1 (0x01) | PEN_AUTHORIZED | Pen authorization successful | - |
2 (0x02) | PEN_PASSWORD_REQUEST | Password request | - |
4 (0x04) | PEN_DISCONNECTED | Pen disconnected | - |
6 (0x06) | PEN_CONNECTION_SUCCESS | Pen connection successful | - |
17 (0x11) | PEN_SETTING_INFO | Pen status information (battery, memory, etc.) | Battery information during pen charging -> 128 |
18 (0x12) | PEN_SETUP_SUCCESS | Pen setup change successful | - |
19 (0x13) | PEN_SETUP_FAILURE | Pen setup change failed | - |
26 (0x1a) | PEN_USING_NOTE_SET_RESULT | Real-time handwriting data request result | - |
82 (0x52) | PASSWORD_SETUP_SUCCESS | Password setup successful | - |
83 (0x53) | PASSWORD_SETUP_FAILURE | Password setup failed | - |
84 (0x54) | PEN_ILLEGAL_PASSWORD_0000 | Restriction on new password 0000 | - |
99 (0x63) | EVENT_LOW_BATTERY | Low battery event | - |
100 (0x64) | EVENT_POWER_OFF | Power off event | - |
34 (0x22) | PEN_FW_UPGRADE_STATUS | Pen firmware upgrade status | - |
35 (0x23) | PEN_FW_UPGRADE_SUCCESS | Pen firmware upgrade successful | - |
36 (0x24) | PEN_FW_UPGRADE_FAILURE | Pen firmware upgrade failed | 1=Same version/2=Space insufficient/3=Failure/4=Compression not supported |
37 (0x25) | PEN_FW_UPGRADE_SUSPEND | Pen firmware upgrade suspended | - |
48 (0x30) | OFFLINE_DATA_NOTE_LIST | Offline data note list | - |
49 (0x31) | OFFLINE_DATA_PAGE_LIST | Offline data page list | - |
50 (0x32) | OFFLINE_DATA_SEND_START | Offline data send start | - |
51 (0x33) | OFFLINE_DATA_SEND_STATUS | Offline data sending status | - |
52 (0x34) | OFFLINE_DATA_SEND_SUCCESS | Offline data send successful | - |
53 (0x35) | OFFLINE_DATA_SEND_FAILURE | Offline data send failed | - |
165 (0xa5) | OFFLINE_DATA_DELETE_RESPONSE | Offline data deletion status | - |
84 (0x54) | PEN_CONNECTION_FAILURE_BTDUPLICATE | Failure when attempting to connect duplicate Bluetooth pens | - |
193 (0xc1) | PEN_PROFILE | Pen profile | - |
115 (0x73) | RES_PDS | Pen PDS | - |
104 (0x68) | EVENT_DOT_ERROR | Pen Dot event error | - |
105 (0x69) | EVENT_DOT_PUI | Pen Dot PUI information | - |
244 (0xf4) | RES_LOG_INFO | Pen log information | - |
245 (0xf5) | RES_LOG_DATA | Pen log data | - |
// Usage with React hook
const [controller, setController] = useState();
const [penVersionInfo, setPenVersionInfo] = useState();
const [battery, setBattery] = useState();
useEffect(() => {
PenHelper.messageCallback = async (mac, type, args) => {
messageProcess(mac, type, args);
}
}, []);
const messageProcess = (mac, type, args) => {
switch(type) {
case PenMessageType.PEN_SETTING_INFO:
const _controller = PenHelper.pens.filter((c) => c.info.MacAddress === mac)[0];
setController(_controller); // Register the controller of the corresponding pen.
setBattery(args.Battery); // Save battery status information -> Display 128 when charging
...
break;
case PenMessageType.PEN_DISCONNECTED: // Reset all state values when the pen is disconnected
setController(null);
setPenInfo(null);
setBattery(null);
break;
case PenMessageType.PEN_PASSWORD_REQUEST: ... // Handling password request
onPasswordRequired(args);
break;
case PenMessageType.PEN_SETUP_SUCCESS: // Processing when pen connection is successful
if (controller) {
setPenVersionInfo(controller.info);
}
...
break;
}
}
...
const onPasswordRequired = (args: any) => {
const password = input();
...
if (args.RetryCount >= 10) {
alert('All information on the pen will be reset.');
}
...
controller.InputPassword(password); // Pass the password using the registered pen controller.
}
...
The dot data coming from the pen is processed through the registered callback function handleDot
in the penController.
handleDot = (controller: any, args: any) => { ... }
This logic is used to convert general ncode dot coordinate values according to the view size so that they can be displayed in the view.
/**
* This function is to convert the general ncode dot coordinate values ββaccording to the view size in order to be shown in the view.
*
* @param {Dot} dot
* @param {View} view
* @param {PaperSize} paperSize
* @returns {ScreenDot}
*/
ncodeToScreen = (dot: Dot, view: View, paperSize: PaperSize) => {
...
}
This logic is used to convert SmartPlate's ncode dot coordinate values ββaccording to the view size so that they can be displayed in the view.
/**
* This function is to convert the SmartPlate ncode dot coordinate values ββaccording to the view size in order to be shown in the view.
*
* @param {Dot} dot
* @param {View} view
* @param {number} angle - possible angle value [0', 90', 180', 270']
* @param {PaperSize} paperSize
* @returns {ScreenDot}
*/
ncodeToScreen_smartPlate = (dot: Dot, view: View, angle: number, paperSize: PaperSize) => {
...
}
// Usage with React hook
useEffect(() => {
PenHelper.dotCallback = async (mac, dot) => {
strokeProcess(dot);
}
}, []);
const strokeProcess = (dot: Dot) => {
...
const view = { width: canvasFb.width, height: canvasFb.height };
let screenDot: ScreenDot;
if (PenHelper.isSamePage(dot.pageInfo, PlateNcode_3)) { // SmartPlate
screenDot = PenHelper.ncodeToScreen_smartPlate(dot, view, angle, paperSize);
} else { // Default
screenDot = PenHelper.ncodeToScreen(dot, view, paperSize);
}
...
}
Logic to distinguish whether it is the same page based on different ncode page information (SOBP). SOBP is information to distinguish pages and stands for Section/Owner/Book/Page.
/**
* This function is to distinguish whether it is the same page based on different ncode page information (SOBP).
*
* @param {PageInfo} page1
* @param {PageInfo} page2
* @returns {boolean}
*/
isSamePage = (page1: PageInfo, page2: PageInfo) => {
...
}
extractMarginInfo, getNoteImage, setNprojInPuiController
This logic extracts the margin info of the ncode page from the nproj based on the pageInfo received from the pen.
/**
* This function is to extract the margin info of the ncode page from nproj based on pageInfo.
*
* @param {string || null} url
* @param {PageInfo} pageInfo
* @returns {PaperSize}
*/
const extractMarginInfo = async (url:string | null, pageInfo: PageInfo) => {
...
}
This logic is used to retrieve the image of the note based on the pageInfo received from the pen.
/**
* This function is to get the note image based on pageInfo.
*
* @param {PageInfo} pageInfo
* @param {React.dispatch} setImageBlobUrl
* @returns {boolean} - success -> setImageBlobUrl(imageBlobUrl)
*/
const getNoteImage = async (pageInfo: PageInfo, setImageBlobUrl: any) => {
...
}
This logic sets the PUI information on the page based on the pageInfo and the url of the nproj file received from the pen. Once registered, this PUI will be returned through the messageCallback when a SmartPen is input.
/**
* This function is to set the PUI in Page based on pageInfo.
*
* @param {string || null} url
* @param {PageInfo} pageInfo
*/
const setNprojInPuiController = async (url: string | null, pageInfo: PageInfo) => {
...
}
// Usage with React hook
const [imageBlobUrl, setImageBlobUrl] = useState<string>();
const [paperSize, setPaperSize] = useState<PaperSize>();
useEffect(() => {
async function getNoteImageUsingAPI(pageInfo) {
await NoteServer.setNprojInPuiController(pageInfo);
await NoteServer.getNoteImage(pageInfo, setImageBlobUrl);
const paperSize: PaperSize = await NoteServer.extractMarginInfo(url, pageInfo);
setPaperSize(paperSize);
}
if (pageInfo) {
getNoteImageUsingAPI(pageInfo);
}
}, [pageInfo]);
RequestVersionInfo, SetPassword, InputPassword, RequestPenStatus, SetRtcTime, SetAutoPowerOffTime, SetPenCapPowerOnOffEnable, SetAutoPowerOnEnable, SetBeepSoundEnable, SetHoverEnable, SetOfflineDataEnable, SetColor, RequestAvailableNotes, RequestOfflineNoteList, RequestOfflinePageList, RequestOfflineData, RequestOfflineDelete, RequestFirmwareInstallation, RequestFirmwareUpload, RequestProfileInfo.., RequestProfileReadValue..
Methods | Parameters | Description |
---|---|---|
RequestVersionInfo | Request the current version of the pen | |
SetPassword | oldone: string, newone: string | Request to change the password set on the pen |
InputPassword | password: string | Send a password to the pen |
RequestPenStatus | Request confirmation of various pen settings | |
SetRtcTime | Request to change the pen's set time to the current time | |
SetAutoPowerOffTime | minute: number | Request to change the pen's set auto shutdown time (up to 3600 minutes) |
SetPenCapPowerOnOffEnable | enable: boolean | Request to change the function of turning on/off the pen using the pen cap |
SetAutoPowerOnEnable | enable: boolean | Request to change the function of turning on the pen using the pen cap or writing |
SetBeepSoundEnable | enable: boolean | Request to change the beep sound function of the pen |
SetHoverEnable | enable: boolean | Request to change the hover function of the pen ( Hover: Visual dot display function for estimating writing position) |
SetOfflineDataEnable | enable: boolean | Request to change the function of storing offline writing data on the pen |
SetColor | color: number | Request to change the LED color of the pen (argb) |
RequestAvailableNotes | sections: number[ ], owners: number[ ], notes: number[ ] | null |
Request transmission of real-time writing data to the pen (If notes is null, request without distinguishing notes) |
RequestOfflineNoteList | section: number, owner: number | Request for page information (book) of offline writing data stored on the pen (If SO is 0, return all note lists) |
RequestOfflinePageList | section: number, owner: number, note: number |
Request for page information (page) of offline writing data stored on the pen (As long as SOB matches, it's a page of the note) |
RequestOfflineData | section: number, owner: number, note: number, deleteOnFinished: boolean, pages: number[ ] |
Request for offline writing data stored on the pen (If P is an empty array, request all pages in the note) (If deleteOnFinished is true, delete the transmitted data when finished) |
RequestOfflineDelete | section: number, owner: number, notes: number[ ] |
Request for deletion of offline writing data stored on the pen |
RequestFirmwareInstallation | file: file, version: string, isCompressed: boolean |
Query to upgrade the installed firmware on the pen |
RequestFirmwareUpload | offset: number, data: Uint8Array, status: number |
Upload firmware data to the pen |
RequestProfileCreate | name: string, password: string | Request to create a profile on the pen |
ReqeustProfileDelete | name: string, password: string | Request to remove the configured profile on the pen |
RequestProfileInfo | name: string | Request for information about the configured profile on the pen |
RequestProfileWriteValue | name: string, passsword: string, data: { [key: string]: any } |
Request to write data in the configured profile on the pen |
RequestProfileReadValue | name: string, keys: string[ ] | Request for information about the data in the configured profile on the pen |
RequestProfileDeleteValue | name: string, password: string, keys: string [ ] |
Request to delete data in the configured profile on the pen |
import { PenHelper, NoteServer, PenMessageType } from 'web_pen_sdk';
/** Connect SmartPen to Web service */
PenHelper.scanPen();
useEffect(() => {
PenHelper.messageCallback = async (mac, type, args) => {
messageProcess(mac, type, args)
}
});
const messageProcess = (mac, type, args) => {
switch(type) {
case PenMessageType.x:
...
}
}
/** Data Parsing from SmartPen */
PenHelper.dotCallback = (mac, dot) => {
strokeProcess(dot);
}
const strokeProcess = (dot: Dot) => {
...
}
/** Use NoteServer.extractMarginInfo() function to get size information of the ncode paper. */
const [paperSize, setPaperSize] = useState<PaperSize>();
const paperSize: PaperSize = await NoteServer.extractMarginInfo(url, pageInfo);
/** Use NoteServer.getNoteImage() function to get image url of the note. */
const [imageBlobUrl, setImageBlobUrl] = useState<string>();
await NoteServer.getNoteImage(pageInfo, setImageBlobUrl);
/**
* Draw on Canvas with SmartPen
* Coordinate Transformation with ncode_dot based on view_size, ncode_size
*/
const strokeProcess = (dot: Dot) => {
const view = { width: canvasFb.width, height: canvasFb.height };
// case Default:
const screenDot = PenHelper.ncodeToScreen(dot, view, paperSize);
// case SmartPlate:
const screenDot = PenHelper.ncodeToScreen_smartPlate(dot, view, angle, paperSize)
/** Create path data using screenDot */
const path = new Path(screenDot.x, screenDot.y);
}
/**
* Set the information for the PUI icon on the page
* Async-await calls are optional, as they are not directly utilized on page changes
*/
(await) NoteServer.setNprojInPuiController(pageInfo)
- Released web_pen_sdk package
- Created a sample page
- Pen Event Handler - Added logic to handle events from the pen (connection, disconnection, password request, etc.)
- Updated readme to reflect the addition of Pen Event Handler
- Added pen disconnection feature and updated the sample page to display battery information
- Clarified that the battery status is 128 when the pen is charging
- PenConfigurationInfo, VersionInfo - Added type declarations
- Updated code according to the definition of PenConfigurationInfo, VersionInfo types
- Updated any type within PenHelper
- DotErrorInfo - Added type declaration
- Error handling for abnormal TimeStamps in Dot events
- Added and modified messageType related to pen password setting, change, and release
- Added and modified messageType related to offline and real-time data
- All Dots except hover go through DotFilter
- Modified Packet Escape logic
- Modified SupportedProtocolVersion
- PEN_CONNECTION_SUCCESS - Added MessageType declaration
- ONLINE_PEN_HOVER_EVENT - Added logic for pen hover events for v2.18
- Modified SupportedProtocolVersion
- Modified the SDK to not automatically setHover
- Profile Feature - Added logic for creating, deleting, and querying pen profiles and creating, deleting, and querying items in profiles
- Firmware Feature - Added logic for firmware update
- PenDisk Init - Added request for initializing the pen disk
- Added code to prevent errors due to overlapping connections during Bluetooth write in a busy communication state
- PUI Feature - Added logic to display a message when clicking on a Smart Class Kit (Boogie Board) PUI with the pen
- PUI Feature - Hardcoded PUI coordinates
- PUI Feature - Converted PUI coordinates from nproj to json for use
- PUI Feature - Rolled back to PUI nproj, added support for PUI on note pages
- PUI Feature - Added url as a parameter to setNprojInPuiController and extractMarginInfo