{"id":39113822,"url":"https://github.com/valiot/stephanex","last_synced_at":"2026-01-17T20:01:24.342Z","repository":{"id":305230697,"uuid":"1022242692","full_name":"valiot/stephanex","owner":"valiot","description":"An Elixir implementation of Weihenstephan Standards Communication Protocol","archived":false,"fork":false,"pushed_at":"2025-07-22T00:48:38.000Z","size":31,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-23T14:58:13.267Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/valiot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-18T17:43:35.000Z","updated_at":"2025-07-22T00:48:42.000Z","dependencies_parsed_at":"2025-07-19T02:22:42.814Z","dependency_job_id":null,"html_url":"https://github.com/valiot/stephanex","commit_stats":null,"previous_names":["valiot/stephanex"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/valiot/stephanex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fstephanex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fstephanex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fstephanex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fstephanex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valiot","download_url":"https://codeload.github.com/valiot/stephanex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fstephanex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28517429,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T18:55:29.170Z","status":"ssl_error","status_checked_at":"2026-01-17T18:55:03.375Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-17T20:01:22.476Z","updated_at":"2026-01-17T20:01:24.299Z","avatar_url":"https://github.com/valiot.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stephanex\n\nA complete Elixir AI re-implementation of the Weihenstephan Standards Protocol (WS Protocol) for communication between industrial beverage filling machines and Data Acquisition systems/Manufacturing Execution Systems based on [WS_Protocol](https://github.com/StefanHasensperling/WS_Protocol) repository.\n\n## About WS Protocol\n\nThe WS Protocol is a binary TCP-based protocol used for data exchange in industrial beverage production environments. It provides a standardized way to communicate with filling machines, allowing MES applications to read production data, machine states, and control parameters.\n\n### Key Features\n\n- **Binary TCP Protocol**: 8-byte message frames over TCP\n- **Simple Request/Response**: Easy to implement and understand\n- **Tag-based Data Exchange**: Structured data points with unique IDs\n- **Multiple Data Types**: Integer, Float, and String values\n- **Access Control**: Read-only, write-only, and read-write permissions\n- **Heartbeat Support**: Automatic connection monitoring\n- **Concurrent Client Support**: Handle multiple clients simultaneously\n\n## Installation\n\nAdd `stephanex` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:stephanex, \"~\u003e 0.1.0\"}\n  ]\nend\n```\n\n## Usage\n\n### Creating a Server\n\nThe server listens for client connections and manages a collection of tags that represent machine data points.\n\n```elixir\n# Start a server on port 5000\n{:ok, server} = WSProtocol.Server.start_link(port: 5000)\n\n# Add tags to the server\nproduction_counter = WSProtocol.Tag.new(1001, \"Production Counter\", :integer, \n  int_value: 0, \n  access: :read_write\n)\n\nmachine_state = WSProtocol.Tag.new(1002, \"Machine State\", :integer, \n  int_value: 1, \n  access: :read_only\n)\n\noperator_message = WSProtocol.Tag.new(2001, \"Operator Message\", :string, \n  string_value: \"Machine Ready\", \n  access: :read_write\n)\n\n# Add tags to server\n:ok = WSProtocol.Server.add_tag(server, production_counter)\n:ok = WSProtocol.Server.add_tag(server, machine_state)\n:ok = WSProtocol.Server.add_tag(server, operator_message)\n```\n\n### Creating a Client\n\nThe client connects to a server and can read/write tag values.\n\n```elixir\n# Start a client\n{:ok, client} = WSProtocol.Client.start_link(host: \"192.168.1.100\", port: 5000)\n\n# Connect to the server\n:ok = WSProtocol.Client.connect(client)\n\n# Check connection status\ntrue = WSProtocol.Client.connected?(client)\n```\n\n### Reading Values\n\n```elixir\n# Read integer values\n{:ok, production_count} = WSProtocol.Client.read_single_value_as_int(client, 1001)\n{:ok, machine_state} = WSProtocol.Client.read_single_value_as_int(client, 1002)\n\n# Read float values\n{:ok, temperature} = WSProtocol.Client.read_single_value_as_float(client, 1003)\n\n# Read string values\n{:ok, message} = WSProtocol.Client.read_single_string(client, 2001)\n```\n\n### Writing Values\n\n```elixir\n# Write integer values\n:ok = WSProtocol.Client.write_single_value(client, 1001, 1500)\n\n# Write float values\n:ok = WSProtocol.Client.write_single_value(client, 1003, 25.5)\n\n# Write string values\n:ok = WSProtocol.Client.write_single_string(client, 2001, \"Production Started\")\n```\n\n### Heartbeat and Connection Monitoring\n\n```elixir\n# Manual heartbeat\n:ok = WSProtocol.Client.no_op(client)\n\n# Automatic heartbeat is enabled by default\n{:ok, client} = WSProtocol.Client.start_link(\n  host: \"192.168.1.100\", \n  port: 5000,\n  heartbeat_enabled: true,\n  heartbeat_interval: 20_000  # 20 seconds\n)\n```\n\n### Server Management\n\n```elixir\n# Update tag values on server\n:ok = WSProtocol.Server.update_tag_value(server, 1001, 2000)\n\n# Get tag information\n{:ok, tag} = WSProtocol.Server.get_tag(server, 1001)\n\n# List all tags\ntags = WSProtocol.Server.list_tags(server)\n\n# Check connected clients\nclient_count = WSProtocol.Server.client_count(server)\n\n# Remove a tag\n:ok = WSProtocol.Server.remove_tag(server, 1001)\n```\n\n## Tag Types and Access Control\n\n### Data Types\n\n- **`:integer`** - 32-bit signed integer values\n- **`:float`** - 32-bit floating point values  \n- **`:string`** - UTF-8 encoded strings\n\n### Access Control\n\n- **`:read_only`** - Tag can only be read by clients\n- **`:write_only`** - Tag can only be written by clients\n- **`:read_write`** - Tag can be both read and written\n\n### Creating Tags\n\n```elixir\n# Integer tag with read-write access\ncounter_tag = WSProtocol.Tag.new(1001, \"Bottle Counter\", :integer,\n  int_value: 0,\n  access: :read_write\n)\n\n# Float tag with read-only access  \ntemperature_tag = WSProtocol.Tag.new(1002, \"Temperature\", :float,\n  real_value: 22.5,\n  access: :read_only\n)\n\n# String tag with write-only access\ncommand_tag = WSProtocol.Tag.new(2001, \"Command\", :string,\n  string_value: \"\",\n  access: :write_only\n)\n```\n\n## Complete Example\n\nHere's a complete example showing a server and client working together:\n\n```elixir\n# Start server\n{:ok, server} = WSProtocol.Server.start_link(port: 5000)\n\n# Add tags\nproduction_tag = WSProtocol.Tag.new(1001, \"Production Counter\", :integer, int_value: 0)\nstatus_tag = WSProtocol.Tag.new(1002, \"Status Message\", :string, string_value: \"Ready\")\n\nWSProtocol.Server.add_tag(server, production_tag)\nWSProtocol.Server.add_tag(server, status_tag)\n\n# Start client\n{:ok, client} = WSProtocol.Client.start_link(host: \"localhost\", port: 5000)\nWSProtocol.Client.connect(client)\n\n# Read initial values\n{:ok, 0} = WSProtocol.Client.read_single_value_as_int(client, 1001)\n{:ok, \"Ready\"} = WSProtocol.Client.read_single_string(client, 1002)\n\n# Update production counter\nWSProtocol.Client.write_single_value(client, 1001, 100)\nWSProtocol.Client.write_single_string(client, 1002, \"Production Running\")\n\n# Read updated values\n{:ok, 100} = WSProtocol.Client.read_single_value_as_int(client, 1001)\n{:ok, \"Production Running\"} = WSProtocol.Client.read_single_string(client, 1002)\n\n# Cleanup\nWSProtocol.Client.disconnect(client)\nWSProtocol.Server.stop(server)\n```\n\n## Protocol Commands\n\nThe WS Protocol supports the following commands:\n\n| Command ID | Command Name | Description |\n|------------|-------------|-------------|\n| 1 | NoOp | Heartbeat message, no operation |\n| 2 | Read Single Value | Read integer/float value |\n| 3 | Write Single Value | Write integer/float value |\n| 8 | Read String | Read string value |\n| 9 | Write String | Write string value |\n\n## Error Handling\n\nThe library provides comprehensive error handling:\n\n```elixir\n# Handle connection errors\ncase WSProtocol.Client.connect(client) do\n  :ok -\u003e :connected\n  {:error, reason} -\u003e {:connection_failed, reason}\nend\n\n# Handle read errors\ncase WSProtocol.Client.read_single_value_as_int(client, 9999) do\n  {:ok, value} -\u003e value\n  {:error, :implausible_argument} -\u003e :tag_not_found\n  {:error, :unauthorized_access} -\u003e :access_denied\n  {:error, :not_connected} -\u003e :client_disconnected\nend\n```\n\n## Configuration Options\n\n### Server Options\n\n- `:port` - TCP port to listen on (default: 5000)\n- `:name` - GenServer name for registration\n\n### Client Options\n\n- `:host` - Server hostname or IP address (required)\n- `:port` - Server port (default: 5000)\n- `:timeout` - Connection timeout in milliseconds (default: 5000)\n- `:heartbeat_enabled` - Enable automatic heartbeat (default: true)\n- `:heartbeat_interval` - Heartbeat interval in milliseconds (default: 20000)\n- `:name` - GenServer name for registration\n\n## Testing\n\nRun the test suite:\n\n```bash\nmix test\n```\n\nThe library includes comprehensive tests covering:\n- Core protocol functionality\n- Client-server communication\n- Tag management\n- Error handling\n- Multi-client scenarios\n- String encoding/decoding\n- Connection management\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\nCopyright (c) 2025 VALIOT\n\n## Contributing\n\nWe welcome contributions to the WSProtocol library! Please follow these guidelines:\n\n1. **Fork the repository** and create a new branch for your feature or bug fix\n2. **Follow the existing code style** and conventions\n3. **Write comprehensive tests** for any new functionality\n4. **Update documentation** as needed\n5. **Ensure all tests pass** by running `mix test`\n6. **Create a pull request** using the provided [pull request template](.github/pull_request_template.md)\n\n### Development Setup\n\n```bash\n# Clone the repository\ngit clone https://github.com/your-org/stephanex.git\ncd stephanex\n\n# Install dependencies\nmix deps.get\n\n# Run tests\nmix test\n\n# Run tests with coverage\nmix test --cover\n```\n\n### Code Style\n\n- Follow standard Elixir conventions\n- Use descriptive function and variable names\n- Add comprehensive documentation with `@doc` and `@spec`\n- Include examples in documentation where helpful\n\n### Reporting Issues\n\nIf you find a bug or have a feature request, please create an issue on GitHub with:\n- A clear description of the problem or feature\n- Steps to reproduce (for bugs)\n- Expected behavior\n- Actual behavior\n- Environment details (Elixir version, OS, etc.)\n\n### Pull Request Process\n\n1. Ensure your changes don't break existing functionality\n2. Add tests for new features\n3. Update documentation as needed\n4. Use the pull request template to provide clear information about your changes\n5. Be responsive to feedback during the review process\n\nThank you for contributing to WSProtocol!\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaliot%2Fstephanex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvaliot%2Fstephanex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaliot%2Fstephanex/lists"}