Jump to content

John

Seeq Team
  • Posts

    11
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by John

  1. @Eolian Tomcini, Is the error showing after the Add-on is packaged and installed with the Add-on Manager? One reason for this may be that the SDK script is not loaded. In your `index.html` be certain import the script. <script src="/api/plugins/sdk/seeq.js"></script>
  2. Good Question. The `api` needs to be initialized prior to being used. This is done with the `getSeeqApi` function. Here is a snippet of what that initialization might look like. // initialize the api variable let api // check if api has already been initialized if (!api) { await getSeeqApi() // Call the function `getSeeqApi()`. .then(async function (_seeq) { // Assign the return value of `getSeeqApi()` to the variable `seeq`. api.set(_seeq) }) .catch((error: Error) => { console.log("getSeeqApi ERROR", error); }); } //Continue to use the api
  3. Hey Eolian, You likely won’t need to install the Jupyter server proxy, as Data Lab Functions/Projects already have this capability built-in. The endpoint definition is placed as a comment on the first line of the cell, incorporating the HTTP method and the endpoint name. A notebook cell that is decorated with a top-line comment resembling a RESTful endpoint. The output of that cell is sent to the front end as a response. For example: # GET /items items = spy.search({ 'Path': 'Example >> Cooling Tower 1 >> Area A', 'Name': 'Compressor' }) items.to_json() When the Data LabFunction is run this cell will automatically be registered as an endpoint accessible via a URL. When invoked it will return the JSON serialized item search. Let's assume this endpoint is in a notebook, api_test.ipynb, and is hosted on https://yousite.seeq.com, the endpoint URL might look something like this: https://preview.seeq.com/data-lab/<ProjectUUID>/functions/notebooks/api_test/endpoints/items. More information about Data Lab Functions and how to invoke them can be found here: To call this endpoint from the JavaScript side, you can use the callDataLabApi function of the Plugin API (more details can be found here). The callDataLabApi function requires the ProjectID, which is generated when the Add-on is installed, although the project name is known. A typical workflow to call an API endpoint from JavaScript is to first find the ID using the getDataLabProject function and then pass it into callDataLabApi. Here is an example. // Assuming API is already available as `api` const projectName = 'YourProjectName'; const notebookName = 'YourNotebookName'; const apiPath = '/api/some-endpoint'; // Step 1: Get the project ID using the project name api.getDataLabProject(projectName) .then((projectResponse) => { const projectId = projectResponse.projectId; if (!projectId) { throw new Error(`Project with name "${projectName}" not found.`); } // Step 2: Call the Data Lab API using the retrieved project ID return api.callDataLabApi({ projectId: projectId, notebookName: notebookName, path: apiPath, method: 'GET', // or 'POST', 'PUT', 'DELETE', etc. query: {}, // Optional: Replace with actual query parameters body: {}, // Optional: Replace with actual body content if needed headers: { } // Optional: Replace with actual headers if needed }); }) .then((dataLabResponse) => { // Step 3: Handle the response console.log('Data Lab API Response:', dataLabResponse); }) .catch((error) => { console.error('Error fetching Data Lab API:', error); }); In your case you mentioned that the output is HTML. In that case you'd send the HTML information as the request and render it on the frontend.
  4. I’d like to get some additional information about the Add-on you are looking to develop. You mention that “For our final product, we will need to pull a few thousand signals at regular intervals”. I’m curious what the use case is for this amount of signals. SPy parallelizes the pull requests and is most likely going to be your most optimal route. By default `spy.pull` pulls 8 items concurrently. This can be adjusted to a little higher number which may help a bit. You can use the following to adjust, but I don't know how much this will help. spy.options.max_concurrent_requests = 16 My other concern is related to memory allocation. During a pull, the item data is held in memory and I’m worried that if you are pulling a few thousand signals that you can run out of memory. It all depends on how many signals and time range you plan on pulling. Chunking the pull into smaller groups of signals may relieve the memory pressure.
  5. Hey Kin, Great questions! Seeq-SysID Add-on Packaging: You're right. The Seeq-SysID Add-on in the Add-on Gallery predates the Add-on Manager and uses a different installation process. It gets installed from the Data Lab terminal through a series of commands. This is acceptable for specific cases, but the newer, packaging approach offers more flexibility for future development. The Add-on Tool Packaging Option: For a more robust and maintainable Add-on, consider the packaging approach that you referenced (Add-on Development). This method allows for flexibility in the types of Add-ons you are able to develop (AddOnTools, Frontend Plugins, and Data Lab Functions). The .addon file is a zip file with your notebook and an addon.json file that describes the structure of Add-on. Once your addon.json file is defined there is an helper build script to create the .addon file (Packaging) However for simpler Add-on Tools, packaging is not necessarily required. Add-on Tool Development (Simple Approach): If you prefer a simpler approach, Add-on Tools (Jupyter Notebooks run in Add-on Mode) are a good option and they don't require formal packaging (.addon file). Here's a helpful guide: How To Develop a Simple Interactive Add-on Tool Publishing and Access Management: Once your Add-on Tool functions as desired, you can publish it for wider use (assuming admin privileges). Here's the process: Development: Complete your code and ensure it meets expectations. Publishing (Admins): Use the User Tool Creator for publishing: Add-on Tool Administration and Development The Add-on Manager automatically adopts the tool within an hour. You can then manage user access through the Add-on Manager. Publishing (Non-Admins): Contact an admin to use the User Tool Creator for you. Overall, the packaging approach is recommended for long-term maintainability and future expansion of your Add-on. However, the Add-on Tool option provides a simpler starting point if needed.
  6. @Nitish, Great question! What kind of Add-on are you developing? Is it an Add-on Tool or a frontend Add-on that uses a Data Lab Function as a backend? If you are developing an Add-on uses a Data Lab Function as a backend then you can directly call the reserved `LOG` variable to write to the Data Lab logger. Lets look at a really simple example of a function in the cell of a Data Lab Functions notebook. def add_ten(number=0): # This function adds 10 to a number LOG.info("Starting the process") try: new_number = number + 10 return new_number except Exception as e # Lets log this failure LOG.error(f"Failed to add ten with error - {e}" Alternatively, you can use the `getLogger` method from the logging module to get the Data Lab Functions Logger: import os import logging my_log = logging.getLogger(os.environ['SEEQ_DATALAB_FUNCTIONS_LOGGER']) my_log.info("Hello World!") The logs for the Data Lab Function can be viewed from : `https://your.seeq.server/data-lab/<DATALAB_PROJECT_ID>/functions/logs` Check out https://support.seeq.com/kb/latest/cloud/reserved-variables#id-(R64)ReservedVariables-TheLOGObject for more information.
  7. Welcome to the Seeq Developer Club Forum! This forum is your go-to destination for all things related to developing Add-ons, API integrations, and leveraging Seeq's capabilities to enhance your projects. Whether you're a seasoned developer or just starting out, this is the place to discuss, share insights, and collaborate with fellow Seeq users. To ensure a positive and productive experience for everyone, please take note of the following guidelines: Public Forum: While we encourage open discussion and collaboration, please refrain from sharing sensitive or confidential information, as this is a public forum accessible to all. Respectful Dialogue: The goal of this forum is to foster respectful and constructive dialogue. Please refrain from behavior that may be considered harassing, threatening, or discriminatory. Resource Utilization: Before posting questions, explore our extensive documentation, tutorials, and the Seeq Support site. You may find answers to your queries or helpful resources that address your needs. Seeq Support - Developing Seeq Add-ons and Connectors Specificity is Key: When posting questions, provide as much detail as possible about your environment, the Seeq version you're using, and any error messages encountered. Screenshots or code snippets can greatly aid in understanding and resolving issues. Constructive Engagement: When responding to questions, aim to be helpful and constructive. Avoid personal attacks or dismissive comments and focus on providing valuable feedback and assistance. We're thrilled to have you as part of our developer community! Let's collaborate, innovate, and empower each other to unlock the full potential of Seeq. Thank you for your participation!
  8. In more recent versions of Seeq (+R58), we have changed our Add-on rendering engine to Voila and renamed the functionality to "Add-on Mode" from "AppMode." The rendered Voila interface is designed for interactivity and is based on widgets. As you've noticed this means that code in a cell may not function the same way in both Jupyter and Voila. This is particularly true around interactions (i.e. inputs). A way to get an input is to use a widget from ipywidgets and then use the value from the widget in your code. Here is a sample code snippet that uses an input widget and renders the value when a button is clicked. import ipywidgets as widgets #Define the input user_input = widgets.Text( value='Hello World', placeholder='Type something', description='String:', disabled=False ) #define a button button = widgets.Button( description="Execute", button_style='success' ) #define an Output - someplace to render the button click output = widgets.Output() #Do something when button is clicked def get_input_value(b): with output: print(user_input.value) button.on_click(get_input_value) #display input, button, and output Vertically widgets.VBox([user_input,button,output]) Tip: In the new Advanced Mode in Seeq Data Lab you can render your notebook without having to navigate to a separate tab. You can access the "Add-on Mode Preview" from the View section in the top menu. For information about the new Advanced Mode Seeq Data Lab check please check out Advanced Mode for Data Lab. Additional Information: ipywidgets
  9. Seeq Version: R21.0.42+ Question: How can i create a signal that forcasts a value out into the future based on some rolling period of historical data? For this example say i want to predict the Area A Temperature 3 days in the future based on the previous week (7 days) of data.
×
×
  • Create New...