Install
$ agentstack add skill-masayuki-kono-agent-skills-moto-hses-usage ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
moto-hses usage guide
This skill provides guidance for using the moto-hses crate family to communicate with Yaskawa robot controllers via the High Speed Ethernet Server (HSES) protocol.
> Note: The moto-hses crate family is a Rust client implementation for the HSES protocol. For the underlying protocol specification (message structure, command IDs, error codes), see the hses-protocol skill.
When to Use
- Implementing HSES communication with Yaskawa robot controllers in Rust
- Using
moto_hses_client,moto_hses_proto, ormoto_hses_mockcrates - Looking up API methods for robot control, status reading, variable access, file operations
- Writing tests with MockServer for HSES communication
Crate Overview
| Crate | Purpose | |-------|---------| | moto_hses_client | HSES client for communicating with robot controllers | | moto_hses_proto | Protocol types (Status, commands, etc.) | | moto_hses_mock | Mock server for integration testing |
Key Types
| Type | Description | |------|-------------| | HsesClient | Basic HSES client (single-task usage) | | SharedHsesClient | Thread-safe wrapper for concurrent access from multiple tasks | | HsesClientOps | Trait for client abstraction (implemented by both client types) |
Client Connection
Basic Usage
use moto_hses_client::{ClientConfig, HsesClient};
use moto_hses_proto::{ROBOT_CONTROL_PORT, FILE_CONTROL_PORT, TextEncoding};
use std::time::Duration;
// Create configuration
let config = ClientConfig {
host: "192.168.1.100".to_string(),
port: ROBOT_CONTROL_PORT, // 10040 for robot control
timeout: Duration::from_millis(3000),
retry_count: 0,
retry_delay: Duration::from_millis(200),
buffer_size: 8192,
text_encoding: TextEncoding::ShiftJis,
};
// Connect to controller
let client = HsesClient::new_with_config(config).await?;
Port Constants
| Constant | Port | Usage | |----------|------|-------| | ROBOT_CONTROL_PORT | 10040 | Status, servo, job, variable, I/O, register operations | | FILE_CONTROL_PORT | 10041 | File transfer operations (send/receive/delete) |
Thread-Safe Client (SharedHsesClient)
For concurrent access from multiple tasks, wrap HsesClient with SharedHsesClient:
use moto_hses_client::{HsesClient, HsesClientOps, SharedHsesClient};
// Create HsesClient and wrap it for thread-safe access
let client = HsesClient::new_with_config(config).await?;
let shared_client = SharedHsesClient::new(client);
// Clone for each concurrent task
let client1 = shared_client.clone();
let client2 = shared_client.clone();
let handle1 = tokio::spawn(async move {
client1.read_status().await
});
let handle2 = tokio::spawn(async move {
client2.read_position(0).await
});
// Wait for all tasks
let (result1, result2) = tokio::try_join!(handle1, handle2)?;
HsesClientOps Trait
Both HsesClient and SharedHsesClient implement the HsesClientOps trait, enabling abstraction:
use moto_hses_client::HsesClientOps;
/// Accepts any client type implementing HsesClientOps
async fn check_status(client: &impl HsesClientOps) -> Result {
let status = client.read_status().await?;
Ok(status.is_running())
}
// Works with both client types
check_status(&client).await?; // HsesClient
check_status(&shared_client).await?; // SharedHsesClient
HsesClient API
Status & Control
| Method | Description | |--------|-------------| | read_status() | Read complete status (Data 1 & Data 2) | | read_status_data1() | Read status data 1 only | | read_status_data2() | Read status data 2 only | | set_servo(bool) | Turn servo ON/OFF | | set_hold(bool) | Set/release hold state | | set_hlock(bool) | Set/release HLOCK (interlock PP and I/O) | | set_cycle_mode(CycleMode) | Set cycle mode (Step/OneCycle/Continuous) |
Status Convenience Methods
The Status struct returned by read_status() provides these helper methods:
| Method | Description | |--------|-------------| | is_running() | Check if robot is running | | is_servo_on() | Check if servo is ON | | has_alarm() | Check if alarm is active | | has_error() | Check if error is active | | is_teach_mode() | Check if in teach mode | | is_play_mode() | Check if in play mode | | is_remote_mode() | Check if in remote mode |
CycleMode Enum (moto_hses_proto::CycleMode)
| Variant | Description | |---------|-------------| | CycleMode::Step | Execute one instruction at a time | | CycleMode::OneCycle | Execute job once and stop | | CycleMode::Continuous | Execute job repeatedly |
Job Control
| Method | Description | |--------|-------------| | select_job(select_type, job_name, line_number) | Select job for execution | | start_job() | Start the selected job | | read_executing_job_info(task_type, attribute) | Read executing job info | | read_executing_job_info_complete(task_type) | Read all job info attributes |
JobSelectType Enum (moto_hses_proto::commands::JobSelectType)
| Variant | Description | |---------|-------------| | JobSelectType::InExecution | Select job for current task | | JobSelectType::MasterJob | Select as master job |
> Note: Job name does not require .JBI extension.
Position
| Method | Description | |--------|-------------| | read_position(control_group) | Read current position |
Alarm
| Method | Description | |--------|-------------| | read_alarm_data(instance, attribute) | Read alarm data | | read_alarm_history(instance, attribute) | Read alarm history | | reset_alarm() | Reset active alarms | | cancel_error() | Cancel current error |
AlarmAttribute Enum (moto_hses_proto::AlarmAttribute)
| Variant | Description | |---------|-------------| | AlarmAttribute::All | Read all alarm attributes | | AlarmAttribute::Code | Read alarm code only | | AlarmAttribute::Data | Read alarm data only | | AlarmAttribute::Type | Read alarm type only | | AlarmAttribute::Time | Read alarm time only | | AlarmAttribute::Name | Read alarm name only |
Alarm Instance Ranges
| Range | Type | |-------|------| | 1-10 | Major failure alarm history | | 1001-1010 | Monitor alarm history |
Variable (Single)
| Method | Description | |--------|-------------| | read_u8(index) / write_u8(index, value) | B-type (8-bit unsigned) | | read_i16(index) / write_i16(index, value) | I-type (16-bit signed) | | read_i32(index) / write_i32(index, value) | D-type (32-bit signed) | | read_f32(index) / write_f32(index, value) | R-type (32-bit float) | | read_string(index) / write_string(index, value) | S-type (string, 16 bytes max) |
Variable (Multiple)
| Method | Description | |--------|-------------| | read_multiple_u8(start, count) / write_multiple_u8(start, values) | B-type | | read_multiple_i16(start, count) / write_multiple_i16(start, values) | I-type | | read_multiple_i32(start, count) / write_multiple_i32(start, values) | D-type | | read_multiple_f32(start, count) / write_multiple_f32(start, values) | R-type | | read_multiple_strings(start, count) / write_multiple_strings(start, values) | S-type |
I/O
| Method | Description | |--------|-------------| | read_io(io_number) / write_io(io_number, value) | Single I/O | | read_multiple_io(start, count) / write_multiple_io(start, data) | Multiple I/O |
Register
| Method | Description | |--------|-------------| | read_register(number) / write_register(number, value) | Single register | | read_multiple_registers(start, count) / write_multiple_registers(start, values) | Multiple registers |
File
> Note: File operations require connecting to FILE_CONTROL_PORT (10041), not ROBOT_CONTROL_PORT.
| Method | Description | |--------|-------------| | read_file_list(pattern) | Get file list (e.g., "*.JBI") | | send_file(filename, content) | Send file to controller | | receive_file(filename) | Receive file from controller | | delete_file(filename) | Delete file from controller |
Error Handling
All async methods return Result. Common error patterns:
use moto_hses_client::ClientError;
match client.read_status().await {
Ok(status) => { /* handle success */ }
Err(ClientError::TimeoutError(_)) => { /* connection timeout */ }
Err(ClientError::ConnectionError(_)) => { /* I/O error */ }
Err(ClientError::ConnectionFailed(retries)) => { /* connection failed after retries */ }
Err(ClientError::ProtocolError(_)) => { /* protocol-level error */ }
Err(ClientError::InvalidVariable(_)) => { /* invalid variable access */ }
Err(ClientError::SystemError(_)) => { /* system error */ }
}
Testing
Unit Tests
Use the HsesClientOps trait (see [HsesClientOps Trait](#hsesclientops-trait) section) for dependency injection and mock implementations in unit tests.
use moto_hses_client::{ClientError, HsesClientOps};
use moto_hses_proto::Status;
// Create a mock implementation for unit testing
struct MockClient {
status: Status,
}
#[async_trait::async_trait]
impl HsesClientOps for MockClient {
async fn read_status(&self) -> Result {
Ok(self.status.clone())
}
// ... implement other methods as needed
}
// Use in tests
async fn handler(client: &impl HsesClientOps) -> Result {
let status = client.read_status().await?;
Ok(status.is_running())
}
Integration Tests with MockServer
Use moto_hses_mock::MockServer for integration testing with actual network communication.
use moto_hses_mock::{MockConfig, MockServer};
let config = MockConfig::new("127.0.0.1", 10040, 10041);
let server = Arc::new(MockServer::new(config).await?);
tokio::spawn({
let server = Arc::clone(&server);
async move { server.run().await.ok(); }
});
tokio::time::sleep(Duration::from_millis(200)).await;
State Access
// Get state reference
let state = server.state();
// Read state (async)
let guard = state.read().await;
assert!(guard.servo_on);
assert!(guard.get_running());
// Write state (async)
let mut guard = state.write().await;
guard.set_servo(true);
guard.set_hold(false);
guard.set_running(true);
MockState Methods
| Method | Description | |--------|-------------| | set_servo(bool) | Set servo ON/OFF state | | set_hold(bool) | Set hold state | | set_running(bool) | Set running state | | get_running() | Get running state | | set_executing_job(Option) | Set executing job info | | get_variable(index) | Get variable value | | set_variable(index, value) | Set variable value | | get_io_state(io_number) | Get I/O state | | set_io_state(io_number, state) | Set I/O state |
If a method for the desired state doesn't exist, you can directly access the public fields of MockState (e.g., guard.status.data1.running).
Important Considerations
Port Conflict Avoidance
- Single-threaded Execution: Configure with
RUST_TEST_THREADS = "1" - Port Management: MockServer uses fixed ports (10040, 10041)
- Test Isolation: Independent MockServer instances prevent state interference between tests
Test Design Best Practices
- State Management: Utilize MockServer's state modification interfaces
- Wait for Async: Add small delays after server start and before assertions
Reference Examples (in references/examples/)
The references/examples/ directory contains sample code for various operations:
| Example | Description | |---------|-------------| | read_status.rs | Status reading and convenience methods | | hold_servo_control.rs | Servo/Hold/Hlock control operations | | cycle_mode_control.rs | Cycle mode setting | | job_select.rs | Job selection | | job_start.rs | Job execution | | position_operations.rs | Robot position reading | | alarm_operations.rs | Alarm data reading and reset | | byte_variable_operations.rs | B-type variable (8-bit unsigned) | | integer_variable_operations.rs | I-type variable (16-bit signed) | | double_variable_operations.rs | D-type variable (32-bit signed) | | real_variable_operations.rs | R-type variable (32-bit float) | | string_variable_operations.rs | S-type variable (string) | | io_operations.rs | I/O data reading and writing | | register_operations.rs | Register data reading and writing | | file_operations.rs | File transfer operations | | read_executing_job_info.rs | Executing job information | | mock_basic_usage.rs | MockServer setup and state configuration | | shared_client.rs | Thread-safe SharedHsesClient for concurrent access |
> Note: For detailed API specifications, refer to the crate documentation on crates.io. The examples above focus on practical usage patterns.
Protocol Reference
For a complete mapping of HSES protocol commands to API methods, see [Protocol Command Reference](references/protocol-commands.md).
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: masayuki-kono
- Source: masayuki-kono/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.